Properly fix bug #8384 - Windows XP clients seem to crash smbd process every once...
[Samba.git] / source3 / rpc_server / spoolss / srv_spoolss_nt.c
blobbfec3cc183a8f90b31ea86d0a348d922f6d4279c
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 /* no idea of the correct error here */
2268 status = WERR_ACCESS_DENIED;
2269 goto done;
2273 /* also check for W32X86/3 if necessary; maybe we already have? */
2275 if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2276 status = winreg_get_driver(info, b,
2277 r->in.architecture,
2278 r->in.driver, 3, &info_win2k);
2279 if (W_ERROR_IS_OK(status)) {
2281 if (delete_files &&
2282 (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2283 printer_driver_files_in_use(info,
2284 get_session_info_system(),
2285 p->msg_ctx,
2286 info_win2k)) {
2287 /* no idea of the correct error here */
2288 talloc_free(info_win2k);
2289 status = WERR_ACCESS_DENIED;
2290 goto done;
2293 /* if we get to here, we now have 2 driver info structures to remove */
2294 /* remove the Win2k driver first*/
2296 status = winreg_del_driver(info, b,
2297 info_win2k,
2300 /* this should not have failed---if it did, report to client */
2302 if (!W_ERROR_IS_OK(status)) {
2303 goto done;
2307 * now delete any associated files if delete_files is
2308 * true. Even if this part failes, we return succes
2309 * because the driver doesn not exist any more
2311 if (delete_files) {
2312 delete_driver_files(get_session_info_system(),
2313 info_win2k);
2318 status = winreg_del_driver(info, b,
2319 info,
2320 version);
2321 if (!W_ERROR_IS_OK(status)) {
2322 goto done;
2326 * now delete any associated files if delete_files is
2327 * true. Even if this part failes, we return succes
2328 * because the driver doesn not exist any more
2330 if (delete_files) {
2331 delete_driver_files(get_session_info_system(), info);
2334 done:
2335 talloc_free(info);
2336 return status;
2340 /********************************************************************
2341 GetPrinterData on a printer server Handle.
2342 ********************************************************************/
2344 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2345 const char *value,
2346 enum winreg_Type *type,
2347 union spoolss_PrinterData *data)
2349 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2351 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2352 *type = REG_DWORD;
2353 data->value = 0x00;
2354 return WERR_OK;
2357 if (!StrCaseCmp(value, "BeepEnabled")) {
2358 *type = REG_DWORD;
2359 data->value = 0x00;
2360 return WERR_OK;
2363 if (!StrCaseCmp(value, "EventLog")) {
2364 *type = REG_DWORD;
2365 /* formally was 0x1b */
2366 data->value = 0x00;
2367 return WERR_OK;
2370 if (!StrCaseCmp(value, "NetPopup")) {
2371 *type = REG_DWORD;
2372 data->value = 0x00;
2373 return WERR_OK;
2376 if (!StrCaseCmp(value, "MajorVersion")) {
2377 *type = REG_DWORD;
2379 /* Windows NT 4.0 seems to not allow uploading of drivers
2380 to a server that reports 0x3 as the MajorVersion.
2381 need to investigate more how Win2k gets around this .
2382 -- jerry */
2384 if (RA_WINNT == get_remote_arch()) {
2385 data->value = 0x02;
2386 } else {
2387 data->value = 0x03;
2390 return WERR_OK;
2393 if (!StrCaseCmp(value, "MinorVersion")) {
2394 *type = REG_DWORD;
2395 data->value = 0x00;
2396 return WERR_OK;
2399 /* REG_BINARY
2400 * uint32_t size = 0x114
2401 * uint32_t major = 5
2402 * uint32_t minor = [0|1]
2403 * uint32_t build = [2195|2600]
2404 * extra unicode string = e.g. "Service Pack 3"
2406 if (!StrCaseCmp(value, "OSVersion")) {
2407 DATA_BLOB blob;
2408 enum ndr_err_code ndr_err;
2409 struct spoolss_OSVersion os;
2411 os.major = 5; /* Windows 2000 == 5.0 */
2412 os.minor = 0;
2413 os.build = 2195; /* build */
2414 os.extra_string = ""; /* leave extra string empty */
2416 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2417 (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2418 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2419 return WERR_GENERAL_FAILURE;
2422 *type = REG_BINARY;
2423 data->binary = blob;
2425 return WERR_OK;
2429 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2430 *type = REG_SZ;
2432 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2433 W_ERROR_HAVE_NO_MEMORY(data->string);
2435 return WERR_OK;
2438 if (!StrCaseCmp(value, "Architecture")) {
2439 *type = REG_SZ;
2440 data->string = talloc_strdup(mem_ctx,
2441 lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2442 W_ERROR_HAVE_NO_MEMORY(data->string);
2444 return WERR_OK;
2447 if (!StrCaseCmp(value, "DsPresent")) {
2448 *type = REG_DWORD;
2450 /* only show the publish check box if we are a
2451 member of a AD domain */
2453 if (lp_security() == SEC_ADS) {
2454 data->value = 0x01;
2455 } else {
2456 data->value = 0x00;
2458 return WERR_OK;
2461 if (!StrCaseCmp(value, "DNSMachineName")) {
2462 const char *hostname = get_mydnsfullname();
2464 if (!hostname) {
2465 return WERR_BADFILE;
2468 *type = REG_SZ;
2469 data->string = talloc_strdup(mem_ctx, hostname);
2470 W_ERROR_HAVE_NO_MEMORY(data->string);
2472 return WERR_OK;
2475 *type = REG_NONE;
2477 return WERR_INVALID_PARAM;
2480 /****************************************************************
2481 _spoolss_GetPrinterData
2482 ****************************************************************/
2484 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2485 struct spoolss_GetPrinterData *r)
2487 struct spoolss_GetPrinterDataEx r2;
2489 r2.in.handle = r->in.handle;
2490 r2.in.key_name = "PrinterDriverData";
2491 r2.in.value_name = r->in.value_name;
2492 r2.in.offered = r->in.offered;
2493 r2.out.type = r->out.type;
2494 r2.out.data = r->out.data;
2495 r2.out.needed = r->out.needed;
2497 return _spoolss_GetPrinterDataEx(p, &r2);
2500 /*********************************************************
2501 Connect to the client machine.
2502 **********************************************************/
2504 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2505 struct sockaddr_storage *client_ss, const char *remote_machine)
2507 NTSTATUS ret;
2508 struct cli_state *the_cli;
2509 struct sockaddr_storage rm_addr;
2510 char addr[INET6_ADDRSTRLEN];
2512 if ( is_zero_addr(client_ss) ) {
2513 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2514 remote_machine));
2515 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2516 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2517 return false;
2519 print_sockaddr(addr, sizeof(addr), &rm_addr);
2520 } else {
2521 rm_addr = *client_ss;
2522 print_sockaddr(addr, sizeof(addr), &rm_addr);
2523 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2524 addr));
2527 if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2528 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2529 addr));
2530 return false;
2533 /* setup the connection */
2534 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2535 &rm_addr, 0, "IPC$", "IPC",
2536 "", /* username */
2537 "", /* domain */
2538 "", /* password */
2539 0, lp_client_signing());
2541 if ( !NT_STATUS_IS_OK( ret ) ) {
2542 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2543 remote_machine ));
2544 return false;
2547 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2548 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2549 cli_shutdown(the_cli);
2550 return false;
2554 * Ok - we have an anonymous connection to the IPC$ share.
2555 * Now start the NT Domain stuff :-).
2558 ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2559 if (!NT_STATUS_IS_OK(ret)) {
2560 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2561 remote_machine, nt_errstr(ret)));
2562 cli_shutdown(the_cli);
2563 return false;
2566 return true;
2569 /***************************************************************************
2570 Connect to the client.
2571 ****************************************************************************/
2573 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2574 uint32_t localprinter,
2575 enum winreg_Type type,
2576 struct policy_handle *handle,
2577 struct notify_back_channel **_chan,
2578 struct sockaddr_storage *client_ss,
2579 struct messaging_context *msg_ctx)
2581 WERROR result;
2582 NTSTATUS status;
2583 struct notify_back_channel *chan;
2585 for (chan = back_channels; chan; chan = chan->next) {
2586 if (memcmp(&chan->client_address, client_ss,
2587 sizeof(struct sockaddr_storage)) == 0) {
2588 break;
2593 * If it's the first connection, contact the client
2594 * and connect to the IPC$ share anonymously
2596 if (!chan) {
2597 fstring unix_printer;
2599 /* the +2 is to strip the leading 2 backslashs */
2600 fstrcpy(unix_printer, printer + 2);
2602 chan = talloc_zero(back_channels, struct notify_back_channel);
2603 if (!chan) {
2604 return false;
2606 chan->client_address = *client_ss;
2608 if (!spoolss_connect_to_client(&chan->cli_pipe, client_ss, unix_printer)) {
2609 TALLOC_FREE(chan);
2610 return false;
2612 chan->binding_handle = chan->cli_pipe->binding_handle;
2614 DLIST_ADD(back_channels, chan);
2616 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2617 receive_notify2_message_list);
2618 /* Tell the connections db we're now interested in printer
2619 * notify messages. */
2620 serverid_register_msg_flags(messaging_server_id(msg_ctx),
2621 true, FLAG_MSG_PRINT_NOTIFY);
2625 * Tell the specific printing tdb we want messages for this printer
2626 * by registering our PID.
2629 if (!print_notify_register_pid(snum)) {
2630 DEBUG(0, ("Failed to register our pid for printer %s\n",
2631 printer));
2634 status = dcerpc_spoolss_ReplyOpenPrinter(chan->binding_handle,
2635 talloc_tos(),
2636 printer,
2637 localprinter,
2638 type,
2640 NULL,
2641 handle,
2642 &result);
2643 if (!NT_STATUS_IS_OK(status)) {
2644 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2645 result = ntstatus_to_werror(status);
2646 } else if (!W_ERROR_IS_OK(result)) {
2647 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2650 chan->active_connections++;
2651 *_chan = chan;
2653 return (W_ERROR_IS_OK(result));
2656 /****************************************************************
2657 ****************************************************************/
2659 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2660 const struct spoolss_NotifyOption *r)
2662 struct spoolss_NotifyOption *option;
2663 uint32_t i,k;
2665 if (!r) {
2666 return NULL;
2669 option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2670 if (!option) {
2671 return NULL;
2674 *option = *r;
2676 if (!option->count) {
2677 return option;
2680 option->types = talloc_zero_array(option,
2681 struct spoolss_NotifyOptionType, option->count);
2682 if (!option->types) {
2683 talloc_free(option);
2684 return NULL;
2687 for (i=0; i < option->count; i++) {
2688 option->types[i] = r->types[i];
2690 if (option->types[i].count) {
2691 option->types[i].fields = talloc_zero_array(option,
2692 union spoolss_Field, option->types[i].count);
2693 if (!option->types[i].fields) {
2694 talloc_free(option);
2695 return NULL;
2697 for (k=0; k<option->types[i].count; k++) {
2698 option->types[i].fields[k] =
2699 r->types[i].fields[k];
2704 return option;
2707 /****************************************************************
2708 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2710 * before replying OK: status=0 a rpc call is made to the workstation
2711 * asking ReplyOpenPrinter
2713 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2714 * called from api_spoolss_rffpcnex
2715 ****************************************************************/
2717 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2718 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2720 int snum = -1;
2721 struct spoolss_NotifyOption *option = r->in.notify_options;
2722 struct sockaddr_storage client_ss;
2724 /* store the notify value in the printer struct */
2726 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2728 if (!Printer) {
2729 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2730 "Invalid handle (%s:%u:%u).\n",
2731 OUR_HANDLE(r->in.handle)));
2732 return WERR_BADFID;
2735 Printer->notify.flags = r->in.flags;
2736 Printer->notify.options = r->in.options;
2737 Printer->notify.printerlocal = r->in.printer_local;
2738 Printer->notify.msg_ctx = p->msg_ctx;
2740 TALLOC_FREE(Printer->notify.option);
2741 Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2743 fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2745 /* Connect to the client machine and send a ReplyOpenPrinter */
2747 if ( Printer->printer_type == SPLHND_SERVER)
2748 snum = -1;
2749 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2750 !get_printer_snum(p, r->in.handle, &snum, NULL) )
2751 return WERR_BADFID;
2753 DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2754 "client_address is %s\n", p->client_id->addr));
2756 if (!lp_print_notify_backchannel(snum)) {
2757 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2758 "backchannel disabled\n"));
2759 return WERR_SERVER_UNAVAILABLE;
2762 if (!interpret_string_addr(&client_ss, p->client_id->addr,
2763 AI_NUMERICHOST)) {
2764 return WERR_SERVER_UNAVAILABLE;
2767 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2768 Printer->notify.printerlocal, REG_SZ,
2769 &Printer->notify.cli_hnd,
2770 &Printer->notify.cli_chan,
2771 &client_ss, p->msg_ctx)) {
2772 return WERR_SERVER_UNAVAILABLE;
2775 return WERR_OK;
2778 /*******************************************************************
2779 * fill a notify_info_data with the servername
2780 ********************************************************************/
2782 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2783 int snum,
2784 struct spoolss_Notify *data,
2785 print_queue_struct *queue,
2786 struct spoolss_PrinterInfo2 *pinfo2,
2787 TALLOC_CTX *mem_ctx)
2789 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2792 /*******************************************************************
2793 * fill a notify_info_data with the printername (not including the servername).
2794 ********************************************************************/
2796 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2797 int snum,
2798 struct spoolss_Notify *data,
2799 print_queue_struct *queue,
2800 struct spoolss_PrinterInfo2 *pinfo2,
2801 TALLOC_CTX *mem_ctx)
2803 /* the notify name should not contain the \\server\ part */
2804 const char *p = strrchr(pinfo2->printername, '\\');
2806 if (!p) {
2807 p = pinfo2->printername;
2808 } else {
2809 p++;
2812 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2815 /*******************************************************************
2816 * fill a notify_info_data with the servicename
2817 ********************************************************************/
2819 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2820 int snum,
2821 struct spoolss_Notify *data,
2822 print_queue_struct *queue,
2823 struct spoolss_PrinterInfo2 *pinfo2,
2824 TALLOC_CTX *mem_ctx)
2826 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2829 /*******************************************************************
2830 * fill a notify_info_data with the port name
2831 ********************************************************************/
2833 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2834 int snum,
2835 struct spoolss_Notify *data,
2836 print_queue_struct *queue,
2837 struct spoolss_PrinterInfo2 *pinfo2,
2838 TALLOC_CTX *mem_ctx)
2840 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2843 /*******************************************************************
2844 * fill a notify_info_data with the printername
2845 * but it doesn't exist, have to see what to do
2846 ********************************************************************/
2848 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2849 int snum,
2850 struct spoolss_Notify *data,
2851 print_queue_struct *queue,
2852 struct spoolss_PrinterInfo2 *pinfo2,
2853 TALLOC_CTX *mem_ctx)
2855 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2858 /*******************************************************************
2859 * fill a notify_info_data with the comment
2860 ********************************************************************/
2862 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2863 int snum,
2864 struct spoolss_Notify *data,
2865 print_queue_struct *queue,
2866 struct spoolss_PrinterInfo2 *pinfo2,
2867 TALLOC_CTX *mem_ctx)
2869 const char *p;
2871 if (*pinfo2->comment == '\0') {
2872 p = lp_comment(snum);
2873 } else {
2874 p = pinfo2->comment;
2877 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2880 /*******************************************************************
2881 * fill a notify_info_data with the comment
2882 * location = "Room 1, floor 2, building 3"
2883 ********************************************************************/
2885 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2886 int snum,
2887 struct spoolss_Notify *data,
2888 print_queue_struct *queue,
2889 struct spoolss_PrinterInfo2 *pinfo2,
2890 TALLOC_CTX *mem_ctx)
2892 const char *loc = pinfo2->location;
2893 NTSTATUS status;
2895 status = printer_list_get_printer(mem_ctx,
2896 pinfo2->sharename,
2897 NULL,
2898 &loc,
2899 NULL);
2900 if (NT_STATUS_IS_OK(status)) {
2901 if (loc == NULL) {
2902 loc = pinfo2->location;
2906 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, loc);
2909 /*******************************************************************
2910 * fill a notify_info_data with the device mode
2911 * jfm:xxxx don't to it for know but that's a real problem !!!
2912 ********************************************************************/
2914 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2915 int snum,
2916 struct spoolss_Notify *data,
2917 print_queue_struct *queue,
2918 struct spoolss_PrinterInfo2 *pinfo2,
2919 TALLOC_CTX *mem_ctx)
2921 /* for a dummy implementation we have to zero the fields */
2922 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2925 /*******************************************************************
2926 * fill a notify_info_data with the separator file name
2927 ********************************************************************/
2929 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2930 int snum,
2931 struct spoolss_Notify *data,
2932 print_queue_struct *queue,
2933 struct spoolss_PrinterInfo2 *pinfo2,
2934 TALLOC_CTX *mem_ctx)
2936 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2939 /*******************************************************************
2940 * fill a notify_info_data with the print processor
2941 * jfm:xxxx return always winprint to indicate we don't do anything to it
2942 ********************************************************************/
2944 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2945 int snum,
2946 struct spoolss_Notify *data,
2947 print_queue_struct *queue,
2948 struct spoolss_PrinterInfo2 *pinfo2,
2949 TALLOC_CTX *mem_ctx)
2951 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2954 /*******************************************************************
2955 * fill a notify_info_data with the print processor options
2956 * jfm:xxxx send an empty string
2957 ********************************************************************/
2959 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2960 int snum,
2961 struct spoolss_Notify *data,
2962 print_queue_struct *queue,
2963 struct spoolss_PrinterInfo2 *pinfo2,
2964 TALLOC_CTX *mem_ctx)
2966 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2969 /*******************************************************************
2970 * fill a notify_info_data with the data type
2971 * jfm:xxxx always send RAW as data type
2972 ********************************************************************/
2974 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2975 int snum,
2976 struct spoolss_Notify *data,
2977 print_queue_struct *queue,
2978 struct spoolss_PrinterInfo2 *pinfo2,
2979 TALLOC_CTX *mem_ctx)
2981 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2984 /*******************************************************************
2985 * fill a notify_info_data with the security descriptor
2986 * jfm:xxxx send an null pointer to say no security desc
2987 * have to implement security before !
2988 ********************************************************************/
2990 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2991 int snum,
2992 struct spoolss_Notify *data,
2993 print_queue_struct *queue,
2994 struct spoolss_PrinterInfo2 *pinfo2,
2995 TALLOC_CTX *mem_ctx)
2997 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
3000 /*******************************************************************
3001 * fill a notify_info_data with the attributes
3002 * jfm:xxxx a samba printer is always shared
3003 ********************************************************************/
3005 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
3006 int snum,
3007 struct spoolss_Notify *data,
3008 print_queue_struct *queue,
3009 struct spoolss_PrinterInfo2 *pinfo2,
3010 TALLOC_CTX *mem_ctx)
3012 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
3015 /*******************************************************************
3016 * fill a notify_info_data with the priority
3017 ********************************************************************/
3019 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
3020 int snum,
3021 struct spoolss_Notify *data,
3022 print_queue_struct *queue,
3023 struct spoolss_PrinterInfo2 *pinfo2,
3024 TALLOC_CTX *mem_ctx)
3026 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
3029 /*******************************************************************
3030 * fill a notify_info_data with the default priority
3031 ********************************************************************/
3033 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
3034 int snum,
3035 struct spoolss_Notify *data,
3036 print_queue_struct *queue,
3037 struct spoolss_PrinterInfo2 *pinfo2,
3038 TALLOC_CTX *mem_ctx)
3040 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
3043 /*******************************************************************
3044 * fill a notify_info_data with the start time
3045 ********************************************************************/
3047 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
3048 int snum,
3049 struct spoolss_Notify *data,
3050 print_queue_struct *queue,
3051 struct spoolss_PrinterInfo2 *pinfo2,
3052 TALLOC_CTX *mem_ctx)
3054 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3057 /*******************************************************************
3058 * fill a notify_info_data with the until time
3059 ********************************************************************/
3061 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3062 int snum,
3063 struct spoolss_Notify *data,
3064 print_queue_struct *queue,
3065 struct spoolss_PrinterInfo2 *pinfo2,
3066 TALLOC_CTX *mem_ctx)
3068 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3071 /*******************************************************************
3072 * fill a notify_info_data with the status
3073 ********************************************************************/
3075 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3076 int snum,
3077 struct spoolss_Notify *data,
3078 print_queue_struct *queue,
3079 struct spoolss_PrinterInfo2 *pinfo2,
3080 TALLOC_CTX *mem_ctx)
3082 print_status_struct status;
3084 print_queue_length(msg_ctx, snum, &status);
3085 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3088 /*******************************************************************
3089 * fill a notify_info_data with the number of jobs queued
3090 ********************************************************************/
3092 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3093 int snum,
3094 struct spoolss_Notify *data,
3095 print_queue_struct *queue,
3096 struct spoolss_PrinterInfo2 *pinfo2,
3097 TALLOC_CTX *mem_ctx)
3099 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3100 data, print_queue_length(msg_ctx, snum, NULL));
3103 /*******************************************************************
3104 * fill a notify_info_data with the average ppm
3105 ********************************************************************/
3107 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3108 int snum,
3109 struct spoolss_Notify *data,
3110 print_queue_struct *queue,
3111 struct spoolss_PrinterInfo2 *pinfo2,
3112 TALLOC_CTX *mem_ctx)
3114 /* always respond 8 pages per minutes */
3115 /* a little hard ! */
3116 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3119 /*******************************************************************
3120 * fill a notify_info_data with username
3121 ********************************************************************/
3123 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3124 int snum,
3125 struct spoolss_Notify *data,
3126 print_queue_struct *queue,
3127 struct spoolss_PrinterInfo2 *pinfo2,
3128 TALLOC_CTX *mem_ctx)
3130 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3133 /*******************************************************************
3134 * fill a notify_info_data with job status
3135 ********************************************************************/
3137 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3138 int snum,
3139 struct spoolss_Notify *data,
3140 print_queue_struct *queue,
3141 struct spoolss_PrinterInfo2 *pinfo2,
3142 TALLOC_CTX *mem_ctx)
3144 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3147 /*******************************************************************
3148 * fill a notify_info_data with job name
3149 ********************************************************************/
3151 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3152 int snum,
3153 struct spoolss_Notify *data,
3154 print_queue_struct *queue,
3155 struct spoolss_PrinterInfo2 *pinfo2,
3156 TALLOC_CTX *mem_ctx)
3158 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3161 /*******************************************************************
3162 * fill a notify_info_data with job status
3163 ********************************************************************/
3165 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3166 int snum,
3167 struct spoolss_Notify *data,
3168 print_queue_struct *queue,
3169 struct spoolss_PrinterInfo2 *pinfo2,
3170 TALLOC_CTX *mem_ctx)
3173 * Now we're returning job status codes we just return a "" here. JRA.
3176 const char *p = "";
3178 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3179 p = "unknown";
3181 switch (queue->status) {
3182 case LPQ_QUEUED:
3183 p = "Queued";
3184 break;
3185 case LPQ_PAUSED:
3186 p = ""; /* NT provides the paused string */
3187 break;
3188 case LPQ_SPOOLING:
3189 p = "Spooling";
3190 break;
3191 case LPQ_PRINTING:
3192 p = "Printing";
3193 break;
3195 #endif /* NO LONGER NEEDED. */
3197 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3200 /*******************************************************************
3201 * fill a notify_info_data with job time
3202 ********************************************************************/
3204 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3205 int snum,
3206 struct spoolss_Notify *data,
3207 print_queue_struct *queue,
3208 struct spoolss_PrinterInfo2 *pinfo2,
3209 TALLOC_CTX *mem_ctx)
3211 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3214 /*******************************************************************
3215 * fill a notify_info_data with job size
3216 ********************************************************************/
3218 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3219 int snum,
3220 struct spoolss_Notify *data,
3221 print_queue_struct *queue,
3222 struct spoolss_PrinterInfo2 *pinfo2,
3223 TALLOC_CTX *mem_ctx)
3225 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3228 /*******************************************************************
3229 * fill a notify_info_data with page info
3230 ********************************************************************/
3231 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3232 int snum,
3233 struct spoolss_Notify *data,
3234 print_queue_struct *queue,
3235 struct spoolss_PrinterInfo2 *pinfo2,
3236 TALLOC_CTX *mem_ctx)
3238 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3241 /*******************************************************************
3242 * fill a notify_info_data with pages printed info.
3243 ********************************************************************/
3244 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3245 int snum,
3246 struct spoolss_Notify *data,
3247 print_queue_struct *queue,
3248 struct spoolss_PrinterInfo2 *pinfo2,
3249 TALLOC_CTX *mem_ctx)
3251 /* Add code when back-end tracks this */
3252 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3255 /*******************************************************************
3256 Fill a notify_info_data with job position.
3257 ********************************************************************/
3259 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3260 int snum,
3261 struct spoolss_Notify *data,
3262 print_queue_struct *queue,
3263 struct spoolss_PrinterInfo2 *pinfo2,
3264 TALLOC_CTX *mem_ctx)
3266 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3269 /*******************************************************************
3270 Fill a notify_info_data with submitted time.
3271 ********************************************************************/
3273 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3274 int snum,
3275 struct spoolss_Notify *data,
3276 print_queue_struct *queue,
3277 struct spoolss_PrinterInfo2 *pinfo2,
3278 TALLOC_CTX *mem_ctx)
3280 data->data.string.string = NULL;
3281 data->data.string.size = 0;
3283 init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3284 &data->data.string.string,
3285 &data->data.string.size);
3289 struct s_notify_info_data_table
3291 enum spoolss_NotifyType type;
3292 uint16_t field;
3293 const char *name;
3294 enum spoolss_NotifyTable variable_type;
3295 void (*fn) (struct messaging_context *msg_ctx,
3296 int snum, struct spoolss_Notify *data,
3297 print_queue_struct *queue,
3298 struct spoolss_PrinterInfo2 *pinfo2,
3299 TALLOC_CTX *mem_ctx);
3302 /* A table describing the various print notification constants and
3303 whether the notification data is a pointer to a variable sized
3304 buffer, a one value uint32_t or a two value uint32_t. */
3306 static const struct s_notify_info_data_table notify_info_data_table[] =
3308 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3309 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3310 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
3311 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3312 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3313 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
3314 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
3315 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3316 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
3317 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3318 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3319 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3320 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
3321 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
3322 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3323 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
3324 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3325 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3326 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
3327 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
3328 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
3329 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
3330 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
3331 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3332 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
3333 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3334 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINTER_NAME, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3335 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_MACHINE_NAME, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3336 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PORT_NAME, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3337 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_USER_NAME, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3338 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_NOTIFY_NAME, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3339 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DATATYPE, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3340 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINT_PROCESSOR, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3341 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PARAMETERS, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3342 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DRIVER_NAME, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3343 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DEVMODE, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3344 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
3345 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS_STRING, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
3346 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
3347 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DOCUMENT, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
3348 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRIORITY, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3349 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_POSITION, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
3350 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SUBMITTED, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
3351 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_START_TIME, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3352 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_UNTIL_TIME, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3353 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TIME, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
3354 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_PAGES, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
3355 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PAGES_PRINTED, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
3356 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_BYTES, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
3359 /*******************************************************************
3360 Return the variable_type of info_data structure.
3361 ********************************************************************/
3363 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3364 uint16_t field)
3366 int i=0;
3368 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3369 if ( (notify_info_data_table[i].type == type) &&
3370 (notify_info_data_table[i].field == field) ) {
3371 return notify_info_data_table[i].variable_type;
3375 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3377 return (enum spoolss_NotifyTable) 0;
3380 /****************************************************************************
3381 ****************************************************************************/
3383 static bool search_notify(enum spoolss_NotifyType type,
3384 uint16_t field,
3385 int *value)
3387 int i;
3389 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3390 if (notify_info_data_table[i].type == type &&
3391 notify_info_data_table[i].field == field &&
3392 notify_info_data_table[i].fn != NULL) {
3393 *value = i;
3394 return true;
3398 return false;
3401 /****************************************************************************
3402 ****************************************************************************/
3404 static void construct_info_data(struct spoolss_Notify *info_data,
3405 enum spoolss_NotifyType type,
3406 uint16_t field, int id)
3408 info_data->type = type;
3409 info_data->field.field = field;
3410 info_data->variable_type = variable_type_of_notify_info_data(type, field);
3411 info_data->job_id = id;
3414 /*******************************************************************
3416 * fill a notify_info struct with info asked
3418 ********************************************************************/
3420 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3421 struct printer_handle *print_hnd,
3422 struct spoolss_NotifyInfo *info,
3423 struct spoolss_PrinterInfo2 *pinfo2,
3424 int snum,
3425 const struct spoolss_NotifyOptionType *option_type,
3426 uint32_t id,
3427 TALLOC_CTX *mem_ctx)
3429 int field_num,j;
3430 enum spoolss_NotifyType type;
3431 uint16_t field;
3433 struct spoolss_Notify *current_data;
3435 type = option_type->type;
3437 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3438 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3439 option_type->count, lp_servicename(snum)));
3441 for(field_num=0; field_num < option_type->count; field_num++) {
3442 field = option_type->fields[field_num].field;
3444 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3446 if (!search_notify(type, field, &j) )
3447 continue;
3449 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3450 struct spoolss_Notify,
3451 info->count + 1);
3452 if (info->notifies == NULL) {
3453 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3454 return false;
3457 current_data = &info->notifies[info->count];
3459 construct_info_data(current_data, type, field, id);
3461 DEBUG(10, ("construct_notify_printer_info: "
3462 "calling [%s] snum=%d printername=[%s])\n",
3463 notify_info_data_table[j].name, snum,
3464 pinfo2->printername));
3466 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3467 NULL, pinfo2, mem_ctx);
3469 info->count++;
3472 return true;
3475 /*******************************************************************
3477 * fill a notify_info struct with info asked
3479 ********************************************************************/
3481 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3482 print_queue_struct *queue,
3483 struct spoolss_NotifyInfo *info,
3484 struct spoolss_PrinterInfo2 *pinfo2,
3485 int snum,
3486 const struct spoolss_NotifyOptionType *option_type,
3487 uint32_t id,
3488 TALLOC_CTX *mem_ctx)
3490 int field_num,j;
3491 enum spoolss_NotifyType type;
3492 uint16_t field;
3493 struct spoolss_Notify *current_data;
3495 DEBUG(4,("construct_notify_jobs_info\n"));
3497 type = option_type->type;
3499 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3500 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3501 option_type->count));
3503 for(field_num=0; field_num<option_type->count; field_num++) {
3504 field = option_type->fields[field_num].field;
3506 if (!search_notify(type, field, &j) )
3507 continue;
3509 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3510 struct spoolss_Notify,
3511 info->count + 1);
3512 if (info->notifies == NULL) {
3513 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3514 return false;
3517 current_data=&(info->notifies[info->count]);
3519 construct_info_data(current_data, type, field, id);
3520 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3521 queue, pinfo2, mem_ctx);
3522 info->count++;
3525 return true;
3529 * JFM: The enumeration is not that simple, it's even non obvious.
3531 * let's take an example: I want to monitor the PRINTER SERVER for
3532 * the printer's name and the number of jobs currently queued.
3533 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3534 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3536 * I have 3 printers on the back of my server.
3538 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3539 * structures.
3540 * Number Data Id
3541 * 1 printer 1 name 1
3542 * 2 printer 1 cjob 1
3543 * 3 printer 2 name 2
3544 * 4 printer 2 cjob 2
3545 * 5 printer 3 name 3
3546 * 6 printer 3 name 3
3548 * that's the print server case, the printer case is even worse.
3551 /*******************************************************************
3553 * enumerate all printers on the printserver
3554 * fill a notify_info struct with info asked
3556 ********************************************************************/
3558 static WERROR printserver_notify_info(struct pipes_struct *p,
3559 struct policy_handle *hnd,
3560 struct spoolss_NotifyInfo *info,
3561 TALLOC_CTX *mem_ctx)
3563 int snum;
3564 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3565 int n_services=lp_numservices();
3566 int i;
3567 struct spoolss_NotifyOption *option;
3568 struct spoolss_NotifyOptionType option_type;
3569 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3570 WERROR result;
3572 DEBUG(4,("printserver_notify_info\n"));
3574 if (!Printer)
3575 return WERR_BADFID;
3577 option = Printer->notify.option;
3579 info->version = 2;
3580 info->notifies = NULL;
3581 info->count = 0;
3583 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3584 sending a ffpcn() request first */
3586 if ( !option )
3587 return WERR_BADFID;
3589 for (i=0; i<option->count; i++) {
3590 option_type = option->types[i];
3592 if (option_type.type != PRINTER_NOTIFY_TYPE)
3593 continue;
3595 for (snum = 0; snum < n_services; snum++) {
3596 if (!lp_browseable(snum) ||
3597 !lp_snum_ok(snum) ||
3598 !lp_print_ok(snum)) {
3599 continue; /* skip */
3602 /* Maybe we should use the SYSTEM session_info here... */
3603 result = winreg_get_printer_internal(mem_ctx,
3604 get_session_info_system(),
3605 p->msg_ctx,
3606 lp_servicename(snum),
3607 &pinfo2);
3608 if (!W_ERROR_IS_OK(result)) {
3609 DEBUG(4, ("printserver_notify_info: "
3610 "Failed to get printer [%s]\n",
3611 lp_servicename(snum)));
3612 continue;
3616 construct_notify_printer_info(p->msg_ctx,
3617 Printer, info,
3618 pinfo2, snum,
3619 &option_type, snum,
3620 mem_ctx);
3622 TALLOC_FREE(pinfo2);
3626 #if 0
3628 * Debugging information, don't delete.
3631 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3632 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3633 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3635 for (i=0; i<info->count; i++) {
3636 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3637 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3638 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3640 #endif
3642 return WERR_OK;
3645 /*******************************************************************
3647 * fill a notify_info struct with info asked
3649 ********************************************************************/
3651 static WERROR printer_notify_info(struct pipes_struct *p,
3652 struct policy_handle *hnd,
3653 struct spoolss_NotifyInfo *info,
3654 TALLOC_CTX *mem_ctx)
3656 int snum;
3657 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3658 int i;
3659 uint32_t id;
3660 struct spoolss_NotifyOption *option;
3661 struct spoolss_NotifyOptionType option_type;
3662 int count,j;
3663 print_queue_struct *queue=NULL;
3664 print_status_struct status;
3665 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3666 WERROR result;
3668 DEBUG(4,("printer_notify_info\n"));
3670 if (!Printer)
3671 return WERR_BADFID;
3673 option = Printer->notify.option;
3674 id = 0x0;
3676 info->version = 2;
3677 info->notifies = NULL;
3678 info->count = 0;
3680 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3681 sending a ffpcn() request first */
3683 if ( !option )
3684 return WERR_BADFID;
3686 if (!get_printer_snum(p, hnd, &snum, NULL)) {
3687 return WERR_BADFID;
3690 /* Maybe we should use the SYSTEM session_info here... */
3691 result = winreg_get_printer_internal(mem_ctx,
3692 get_session_info_system(),
3693 p->msg_ctx,
3694 lp_servicename(snum), &pinfo2);
3695 if (!W_ERROR_IS_OK(result)) {
3696 return WERR_BADFID;
3700 * When sending a PRINTER_NOTIFY_FIELD_SERVER_NAME we should send the
3701 * correct servername.
3703 pinfo2->servername = talloc_strdup(pinfo2, Printer->servername);
3704 if (pinfo2->servername == NULL) {
3705 return WERR_NOMEM;
3708 for (i=0; i<option->count; i++) {
3709 option_type = option->types[i];
3711 switch (option_type.type) {
3712 case PRINTER_NOTIFY_TYPE:
3713 if (construct_notify_printer_info(p->msg_ctx,
3714 Printer, info,
3715 pinfo2, snum,
3716 &option_type, id,
3717 mem_ctx)) {
3718 id--;
3720 break;
3722 case JOB_NOTIFY_TYPE:
3724 count = print_queue_status(p->msg_ctx, snum, &queue,
3725 &status);
3727 for (j=0; j<count; j++) {
3728 construct_notify_jobs_info(p->msg_ctx,
3729 &queue[j], info,
3730 pinfo2, snum,
3731 &option_type,
3732 queue[j].job,
3733 mem_ctx);
3736 SAFE_FREE(queue);
3737 break;
3742 * Debugging information, don't delete.
3745 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3746 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3747 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3749 for (i=0; i<info->count; i++) {
3750 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3751 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3752 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3756 talloc_free(pinfo2);
3757 return WERR_OK;
3760 /****************************************************************
3761 _spoolss_RouterRefreshPrinterChangeNotify
3762 ****************************************************************/
3764 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3765 struct spoolss_RouterRefreshPrinterChangeNotify *r)
3767 struct spoolss_NotifyInfo *info;
3769 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3770 WERROR result = WERR_BADFID;
3772 /* we always have a spoolss_NotifyInfo struct */
3773 info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3774 if (!info) {
3775 result = WERR_NOMEM;
3776 goto done;
3779 *r->out.info = info;
3781 if (!Printer) {
3782 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3783 "Invalid handle (%s:%u:%u).\n",
3784 OUR_HANDLE(r->in.handle)));
3785 goto done;
3788 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3791 * We are now using the change value, and
3792 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3793 * I don't have a global notification system, I'm sending back all the
3794 * information even when _NOTHING_ has changed.
3797 /* We need to keep track of the change value to send back in
3798 RRPCN replies otherwise our updates are ignored. */
3800 Printer->notify.fnpcn = true;
3802 if (Printer->notify.cli_chan != NULL &&
3803 Printer->notify.cli_chan->active_connections > 0) {
3804 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3805 "Saving change value in request [%x]\n",
3806 r->in.change_low));
3807 Printer->notify.change = r->in.change_low;
3810 /* just ignore the spoolss_NotifyOption */
3812 switch (Printer->printer_type) {
3813 case SPLHND_SERVER:
3814 result = printserver_notify_info(p, r->in.handle,
3815 info, p->mem_ctx);
3816 break;
3818 case SPLHND_PRINTER:
3819 result = printer_notify_info(p, r->in.handle,
3820 info, p->mem_ctx);
3821 break;
3824 Printer->notify.fnpcn = false;
3826 done:
3827 return result;
3830 /********************************************************************
3831 ********************************************************************/
3833 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3834 const char *servername,
3835 const char *printername,
3836 const char **printername_p)
3838 /* FIXME: add lp_force_printername() */
3840 if (servername == NULL) {
3841 *printername_p = talloc_strdup(mem_ctx, printername);
3842 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3843 return WERR_OK;
3846 if (servername[0] == '\\' && servername[1] == '\\') {
3847 servername += 2;
3850 *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3851 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3853 return WERR_OK;
3856 /********************************************************************
3857 ********************************************************************/
3859 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3860 const char *printername)
3862 if (dm == NULL) {
3863 return;
3866 dm->devicename = talloc_strndup(dm, printername,
3867 MIN(strlen(printername), 31));
3870 /********************************************************************
3871 * construct_printer_info_0
3872 * fill a printer_info_0 struct
3873 ********************************************************************/
3875 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3876 const struct auth_serversupplied_info *session_info,
3877 struct messaging_context *msg_ctx,
3878 struct spoolss_PrinterInfo2 *info2,
3879 const char *servername,
3880 struct spoolss_PrinterInfo0 *r,
3881 int snum)
3883 int count;
3884 struct printer_session_counter *session_counter;
3885 struct timeval setuptime;
3886 print_status_struct status;
3887 WERROR result;
3889 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3890 if (!W_ERROR_IS_OK(result)) {
3891 return result;
3894 if (servername) {
3895 r->servername = talloc_strdup(mem_ctx, servername);
3896 W_ERROR_HAVE_NO_MEMORY(r->servername);
3897 } else {
3898 r->servername = NULL;
3901 count = print_queue_length(msg_ctx, snum, &status);
3903 /* check if we already have a counter for this printer */
3904 for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3905 if (session_counter->snum == snum)
3906 break;
3909 /* it's the first time, add it to the list */
3910 if (session_counter == NULL) {
3911 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3912 W_ERROR_HAVE_NO_MEMORY(session_counter);
3913 session_counter->snum = snum;
3914 session_counter->counter = 0;
3915 DLIST_ADD(counter_list, session_counter);
3918 /* increment it */
3919 session_counter->counter++;
3921 r->cjobs = count;
3922 r->total_jobs = 0;
3923 r->total_bytes = 0;
3925 get_startup_time(&setuptime);
3926 init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3928 /* JFM:
3929 * the global_counter should be stored in a TDB as it's common to all the clients
3930 * and should be zeroed on samba startup
3932 r->global_counter = session_counter->counter;
3933 r->total_pages = 0;
3934 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3935 SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3936 SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3937 r->free_build = SPOOLSS_RELEASE_BUILD;
3938 r->spooling = 0;
3939 r->max_spooling = 0;
3940 r->session_counter = session_counter->counter;
3941 r->num_error_out_of_paper = 0x0;
3942 r->num_error_not_ready = 0x0; /* number of print failure */
3943 r->job_error = 0x0;
3944 r->number_of_processors = 0x1;
3945 r->processor_type = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3946 r->high_part_total_bytes = 0x0;
3948 /* ChangeID in milliseconds*/
3949 winreg_printer_get_changeid_internal(mem_ctx, session_info, msg_ctx,
3950 info2->sharename, &r->change_id);
3952 r->last_error = WERR_OK;
3953 r->status = nt_printq_status(status.status);
3954 r->enumerate_network_printers = 0x0;
3955 r->c_setprinter = 0x0;
3956 r->processor_architecture = PROCESSOR_ARCHITECTURE_INTEL;
3957 r->processor_level = 0x6; /* 6 ???*/
3958 r->ref_ic = 0;
3959 r->reserved2 = 0;
3960 r->reserved3 = 0;
3962 return WERR_OK;
3966 /********************************************************************
3967 * construct_printer_info1
3968 * fill a spoolss_PrinterInfo1 struct
3969 ********************************************************************/
3971 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3972 const struct spoolss_PrinterInfo2 *info2,
3973 uint32_t flags,
3974 const char *servername,
3975 struct spoolss_PrinterInfo1 *r,
3976 int snum)
3978 WERROR result;
3980 r->flags = flags;
3982 if (info2->comment == NULL || info2->comment[0] == '\0') {
3983 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
3984 } else {
3985 r->comment = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3987 W_ERROR_HAVE_NO_MEMORY(r->comment);
3989 result = create_printername(mem_ctx, servername, info2->printername, &r->name);
3990 if (!W_ERROR_IS_OK(result)) {
3991 return result;
3994 r->description = talloc_asprintf(mem_ctx, "%s,%s,%s",
3995 r->name,
3996 info2->drivername,
3997 r->comment);
3998 W_ERROR_HAVE_NO_MEMORY(r->description);
4000 return WERR_OK;
4003 /********************************************************************
4004 * construct_printer_info2
4005 * fill a spoolss_PrinterInfo2 struct
4006 ********************************************************************/
4008 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
4009 struct messaging_context *msg_ctx,
4010 const struct spoolss_PrinterInfo2 *info2,
4011 const char *servername,
4012 struct spoolss_PrinterInfo2 *r,
4013 int snum)
4015 int count;
4016 print_status_struct status;
4017 WERROR result;
4019 count = print_queue_length(msg_ctx, snum, &status);
4021 if (servername) {
4022 r->servername = talloc_strdup(mem_ctx, servername);
4023 W_ERROR_HAVE_NO_MEMORY(r->servername);
4024 } else {
4025 r->servername = NULL;
4028 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4029 if (!W_ERROR_IS_OK(result)) {
4030 return result;
4033 r->sharename = talloc_strdup(mem_ctx, lp_servicename(snum));
4034 W_ERROR_HAVE_NO_MEMORY(r->sharename);
4035 r->portname = talloc_strdup(mem_ctx, info2->portname);
4036 W_ERROR_HAVE_NO_MEMORY(r->portname);
4037 r->drivername = talloc_strdup(mem_ctx, info2->drivername);
4038 W_ERROR_HAVE_NO_MEMORY(r->drivername);
4040 if (info2->comment[0] == '\0') {
4041 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
4042 } else {
4043 r->comment = talloc_strdup(mem_ctx, info2->comment);
4045 W_ERROR_HAVE_NO_MEMORY(r->comment);
4047 r->location = talloc_strdup(mem_ctx, info2->location);
4048 if (info2->location[0] == '\0') {
4049 const char *loc = NULL;
4050 NTSTATUS nt_status;
4052 nt_status = printer_list_get_printer(mem_ctx,
4053 info2->sharename,
4054 NULL,
4055 &loc,
4056 NULL);
4057 if (NT_STATUS_IS_OK(nt_status)) {
4058 if (loc != NULL) {
4059 r->location = talloc_strdup(mem_ctx, loc);
4063 W_ERROR_HAVE_NO_MEMORY(r->location);
4065 r->sepfile = talloc_strdup(mem_ctx, info2->sepfile);
4066 W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4067 r->printprocessor = talloc_strdup(mem_ctx, info2->printprocessor);
4068 W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4069 r->datatype = talloc_strdup(mem_ctx, info2->datatype);
4070 W_ERROR_HAVE_NO_MEMORY(r->datatype);
4071 r->parameters = talloc_strdup(mem_ctx, info2->parameters);
4072 W_ERROR_HAVE_NO_MEMORY(r->parameters);
4074 r->attributes = info2->attributes;
4076 r->priority = info2->priority;
4077 r->defaultpriority = info2->defaultpriority;
4078 r->starttime = info2->starttime;
4079 r->untiltime = info2->untiltime;
4080 r->status = nt_printq_status(status.status);
4081 r->cjobs = count;
4082 r->averageppm = info2->averageppm;
4084 copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4085 if (!r->devmode) {
4086 DEBUG(8,("Returning NULL Devicemode!\n"));
4089 compose_devicemode_devicename(r->devmode, r->printername);
4091 r->secdesc = NULL;
4093 if (info2->secdesc != NULL) {
4094 /* don't use talloc_steal() here unless you do a deep steal of all
4095 the SEC_DESC members */
4097 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4100 return WERR_OK;
4103 /********************************************************************
4104 * construct_printer_info3
4105 * fill a spoolss_PrinterInfo3 struct
4106 ********************************************************************/
4108 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4109 const struct spoolss_PrinterInfo2 *info2,
4110 const char *servername,
4111 struct spoolss_PrinterInfo3 *r,
4112 int snum)
4114 /* These are the components of the SD we are returning. */
4116 if (info2->secdesc != NULL) {
4117 /* don't use talloc_steal() here unless you do a deep steal of all
4118 the SEC_DESC members */
4120 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4121 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
4124 return WERR_OK;
4127 /********************************************************************
4128 * construct_printer_info4
4129 * fill a spoolss_PrinterInfo4 struct
4130 ********************************************************************/
4132 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4133 const struct spoolss_PrinterInfo2 *info2,
4134 const char *servername,
4135 struct spoolss_PrinterInfo4 *r,
4136 int snum)
4138 WERROR result;
4140 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4141 if (!W_ERROR_IS_OK(result)) {
4142 return result;
4145 if (servername) {
4146 r->servername = talloc_strdup(mem_ctx, servername);
4147 W_ERROR_HAVE_NO_MEMORY(r->servername);
4148 } else {
4149 r->servername = NULL;
4152 r->attributes = info2->attributes;
4154 return WERR_OK;
4157 /********************************************************************
4158 * construct_printer_info5
4159 * fill a spoolss_PrinterInfo5 struct
4160 ********************************************************************/
4162 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4163 const struct spoolss_PrinterInfo2 *info2,
4164 const char *servername,
4165 struct spoolss_PrinterInfo5 *r,
4166 int snum)
4168 WERROR result;
4170 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4171 if (!W_ERROR_IS_OK(result)) {
4172 return result;
4175 r->portname = talloc_strdup(mem_ctx, info2->portname);
4176 W_ERROR_HAVE_NO_MEMORY(r->portname);
4178 r->attributes = info2->attributes;
4180 /* these two are not used by NT+ according to MSDN */
4181 r->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4182 r->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4184 return WERR_OK;
4187 /********************************************************************
4188 * construct_printer_info_6
4189 * fill a spoolss_PrinterInfo6 struct
4190 ********************************************************************/
4192 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4193 struct messaging_context *msg_ctx,
4194 const struct spoolss_PrinterInfo2 *info2,
4195 const char *servername,
4196 struct spoolss_PrinterInfo6 *r,
4197 int snum)
4199 int count;
4200 print_status_struct status;
4202 count = print_queue_length(msg_ctx, snum, &status);
4204 r->status = nt_printq_status(status.status);
4206 return WERR_OK;
4209 /********************************************************************
4210 * construct_printer_info7
4211 * fill a spoolss_PrinterInfo7 struct
4212 ********************************************************************/
4214 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4215 struct messaging_context *msg_ctx,
4216 const char *servername,
4217 struct spoolss_PrinterInfo7 *r,
4218 int snum)
4220 struct auth_serversupplied_info *session_info;
4221 struct GUID guid;
4222 NTSTATUS status;
4224 status = make_session_info_system(mem_ctx, &session_info);
4225 if (!NT_STATUS_IS_OK(status)) {
4226 DEBUG(0, ("construct_printer_info7: "
4227 "Could not create system session_info\n"));
4228 return WERR_NOMEM;
4231 if (is_printer_published(mem_ctx, session_info, msg_ctx,
4232 servername,
4233 lp_servicename(snum), &guid, NULL)) {
4234 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4235 r->action = DSPRINT_PUBLISH;
4236 } else {
4237 r->guid = talloc_strdup(mem_ctx, "");
4238 r->action = DSPRINT_UNPUBLISH;
4240 W_ERROR_HAVE_NO_MEMORY(r->guid);
4242 TALLOC_FREE(session_info);
4243 return WERR_OK;
4246 /********************************************************************
4247 * construct_printer_info8
4248 * fill a spoolss_PrinterInfo8 struct
4249 ********************************************************************/
4251 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4252 const struct spoolss_PrinterInfo2 *info2,
4253 const char *servername,
4254 struct spoolss_DeviceModeInfo *r,
4255 int snum)
4257 WERROR result;
4258 const char *printername;
4260 result = create_printername(mem_ctx, servername, info2->printername, &printername);
4261 if (!W_ERROR_IS_OK(result)) {
4262 return result;
4265 copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4266 if (!r->devmode) {
4267 DEBUG(8,("Returning NULL Devicemode!\n"));
4270 compose_devicemode_devicename(r->devmode, printername);
4272 return WERR_OK;
4276 /********************************************************************
4277 ********************************************************************/
4279 static bool snum_is_shared_printer(int snum)
4281 return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4284 /********************************************************************
4285 Spoolss_enumprinters.
4286 ********************************************************************/
4288 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4289 const struct auth_serversupplied_info *session_info,
4290 struct messaging_context *msg_ctx,
4291 const char *servername,
4292 uint32_t level,
4293 uint32_t flags,
4294 union spoolss_PrinterInfo **info_p,
4295 uint32_t *count_p)
4297 int snum;
4298 int n_services = lp_numservices();
4299 union spoolss_PrinterInfo *info = NULL;
4300 uint32_t count = 0;
4301 WERROR result = WERR_OK;
4302 struct dcerpc_binding_handle *b = NULL;
4304 *count_p = 0;
4305 *info_p = NULL;
4307 for (snum = 0; snum < n_services; snum++) {
4309 const char *printer;
4310 struct spoolss_PrinterInfo2 *info2;
4312 if (!snum_is_shared_printer(snum)) {
4313 continue;
4316 printer = lp_const_servicename(snum);
4318 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4319 printer, snum));
4321 if (b == NULL) {
4322 result = winreg_printer_binding_handle(mem_ctx,
4323 session_info,
4324 msg_ctx,
4325 &b);
4326 if (!W_ERROR_IS_OK(result)) {
4327 goto out;
4331 result = winreg_create_printer(mem_ctx, b,
4332 printer);
4333 if (!W_ERROR_IS_OK(result)) {
4334 goto out;
4337 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4338 union spoolss_PrinterInfo,
4339 count + 1);
4340 if (!info) {
4341 result = WERR_NOMEM;
4342 goto out;
4345 result = winreg_get_printer(mem_ctx, b,
4346 printer, &info2);
4347 if (!W_ERROR_IS_OK(result)) {
4348 goto out;
4351 switch (level) {
4352 case 0:
4353 result = construct_printer_info0(info, session_info,
4354 msg_ctx, info2,
4355 servername,
4356 &info[count].info0, snum);
4357 break;
4358 case 1:
4359 result = construct_printer_info1(info, info2, flags,
4360 servername,
4361 &info[count].info1, snum);
4362 break;
4363 case 2:
4364 result = construct_printer_info2(info, msg_ctx, info2,
4365 servername,
4366 &info[count].info2, snum);
4367 break;
4368 case 4:
4369 result = construct_printer_info4(info, info2,
4370 servername,
4371 &info[count].info4, snum);
4372 break;
4373 case 5:
4374 result = construct_printer_info5(info, info2,
4375 servername,
4376 &info[count].info5, snum);
4377 break;
4379 default:
4380 result = WERR_UNKNOWN_LEVEL;
4381 goto out;
4384 if (!W_ERROR_IS_OK(result)) {
4385 goto out;
4388 count++;
4391 *count_p = count;
4392 *info_p = info;
4394 out:
4395 if (!W_ERROR_IS_OK(result)) {
4396 TALLOC_FREE(info);
4397 return result;
4400 *info_p = info;
4402 return WERR_OK;
4405 /********************************************************************
4406 * handle enumeration of printers at level 0
4407 ********************************************************************/
4409 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4410 const struct auth_serversupplied_info *session_info,
4411 struct messaging_context *msg_ctx,
4412 uint32_t flags,
4413 const char *servername,
4414 union spoolss_PrinterInfo **info,
4415 uint32_t *count)
4417 DEBUG(4,("enum_all_printers_info_0\n"));
4419 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4420 servername, 0, flags, info, count);
4424 /********************************************************************
4425 ********************************************************************/
4427 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4428 const struct auth_serversupplied_info *session_info,
4429 struct messaging_context *msg_ctx,
4430 const char *servername,
4431 uint32_t flags,
4432 union spoolss_PrinterInfo **info,
4433 uint32_t *count)
4435 DEBUG(4,("enum_all_printers_info_1\n"));
4437 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4438 servername, 1, flags, info, count);
4441 /********************************************************************
4442 enum_all_printers_info_1_local.
4443 *********************************************************************/
4445 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4446 const struct auth_serversupplied_info *session_info,
4447 struct messaging_context *msg_ctx,
4448 const char *servername,
4449 union spoolss_PrinterInfo **info,
4450 uint32_t *count)
4452 DEBUG(4,("enum_all_printers_info_1_local\n"));
4454 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4455 servername, PRINTER_ENUM_ICON8, info, count);
4458 /********************************************************************
4459 enum_all_printers_info_1_name.
4460 *********************************************************************/
4462 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4463 const struct auth_serversupplied_info *session_info,
4464 struct messaging_context *msg_ctx,
4465 const char *servername,
4466 union spoolss_PrinterInfo **info,
4467 uint32_t *count)
4469 const char *s = servername;
4471 DEBUG(4,("enum_all_printers_info_1_name\n"));
4473 if ((servername[0] == '\\') && (servername[1] == '\\')) {
4474 s = servername + 2;
4477 if (!is_myname_or_ipaddr(s)) {
4478 return WERR_INVALID_NAME;
4481 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4482 servername, PRINTER_ENUM_ICON8, info, count);
4485 /********************************************************************
4486 enum_all_printers_info_1_network.
4487 *********************************************************************/
4489 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4490 const struct auth_serversupplied_info *session_info,
4491 struct messaging_context *msg_ctx,
4492 const char *servername,
4493 union spoolss_PrinterInfo **info,
4494 uint32_t *count)
4496 const char *s = servername;
4498 DEBUG(4,("enum_all_printers_info_1_network\n"));
4500 /* If we respond to a enum_printers level 1 on our name with flags
4501 set to PRINTER_ENUM_REMOTE with a list of printers then these
4502 printers incorrectly appear in the APW browse list.
4503 Specifically the printers for the server appear at the workgroup
4504 level where all the other servers in the domain are
4505 listed. Windows responds to this call with a
4506 WERR_CAN_NOT_COMPLETE so we should do the same. */
4508 if (servername[0] == '\\' && servername[1] == '\\') {
4509 s = servername + 2;
4512 if (is_myname_or_ipaddr(s)) {
4513 return WERR_CAN_NOT_COMPLETE;
4516 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4517 servername, PRINTER_ENUM_NAME, info, count);
4520 /********************************************************************
4521 * api_spoolss_enumprinters
4523 * called from api_spoolss_enumprinters (see this to understand)
4524 ********************************************************************/
4526 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4527 const struct auth_serversupplied_info *session_info,
4528 struct messaging_context *msg_ctx,
4529 const char *servername,
4530 union spoolss_PrinterInfo **info,
4531 uint32_t *count)
4533 DEBUG(4,("enum_all_printers_info_2\n"));
4535 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4536 servername, 2, 0, info, count);
4539 /********************************************************************
4540 * handle enumeration of printers at level 1
4541 ********************************************************************/
4543 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4544 const struct auth_serversupplied_info *session_info,
4545 struct messaging_context *msg_ctx,
4546 uint32_t flags,
4547 const char *servername,
4548 union spoolss_PrinterInfo **info,
4549 uint32_t *count)
4551 /* Not all the flags are equals */
4553 if (flags & PRINTER_ENUM_LOCAL) {
4554 return enum_all_printers_info_1_local(mem_ctx, session_info,
4555 msg_ctx, servername, info, count);
4558 if (flags & PRINTER_ENUM_NAME) {
4559 return enum_all_printers_info_1_name(mem_ctx, session_info,
4560 msg_ctx, servername, info,
4561 count);
4564 if (flags & PRINTER_ENUM_NETWORK) {
4565 return enum_all_printers_info_1_network(mem_ctx, session_info,
4566 msg_ctx, servername, info,
4567 count);
4570 return WERR_OK; /* NT4sp5 does that */
4573 /********************************************************************
4574 * handle enumeration of printers at level 2
4575 ********************************************************************/
4577 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4578 const struct auth_serversupplied_info *session_info,
4579 struct messaging_context *msg_ctx,
4580 uint32_t flags,
4581 const char *servername,
4582 union spoolss_PrinterInfo **info,
4583 uint32_t *count)
4585 if (flags & PRINTER_ENUM_LOCAL) {
4587 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4588 servername,
4589 info, count);
4592 if (flags & PRINTER_ENUM_NAME) {
4593 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4594 return WERR_INVALID_NAME;
4597 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4598 servername,
4599 info, count);
4602 if (flags & PRINTER_ENUM_REMOTE) {
4603 return WERR_UNKNOWN_LEVEL;
4606 return WERR_OK;
4609 /********************************************************************
4610 * handle enumeration of printers at level 4
4611 ********************************************************************/
4613 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4614 const struct auth_serversupplied_info *session_info,
4615 struct messaging_context *msg_ctx,
4616 uint32_t flags,
4617 const char *servername,
4618 union spoolss_PrinterInfo **info,
4619 uint32_t *count)
4621 DEBUG(4,("enum_all_printers_info_4\n"));
4623 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4624 servername, 4, flags, info, count);
4628 /********************************************************************
4629 * handle enumeration of printers at level 5
4630 ********************************************************************/
4632 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4633 const struct auth_serversupplied_info *session_info,
4634 struct messaging_context *msg_ctx,
4635 uint32_t flags,
4636 const char *servername,
4637 union spoolss_PrinterInfo **info,
4638 uint32_t *count)
4640 DEBUG(4,("enum_all_printers_info_5\n"));
4642 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4643 servername, 5, flags, info, count);
4646 /****************************************************************
4647 _spoolss_EnumPrinters
4648 ****************************************************************/
4650 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4651 struct spoolss_EnumPrinters *r)
4653 const struct auth_serversupplied_info *session_info = get_session_info_system();
4654 WERROR result;
4656 /* that's an [in out] buffer */
4658 if (!r->in.buffer && (r->in.offered != 0)) {
4659 return WERR_INVALID_PARAM;
4662 DEBUG(4,("_spoolss_EnumPrinters\n"));
4664 *r->out.needed = 0;
4665 *r->out.count = 0;
4666 *r->out.info = NULL;
4669 * Level 1:
4670 * flags==PRINTER_ENUM_NAME
4671 * if name=="" then enumerates all printers
4672 * if name!="" then enumerate the printer
4673 * flags==PRINTER_ENUM_REMOTE
4674 * name is NULL, enumerate printers
4675 * Level 2: name!="" enumerates printers, name can't be NULL
4676 * Level 3: doesn't exist
4677 * Level 4: does a local registry lookup
4678 * Level 5: same as Level 2
4681 if (r->in.server && r->in.server[0] == '\0') {
4682 r->in.server = NULL;
4685 switch (r->in.level) {
4686 case 0:
4687 result = enumprinters_level0(p->mem_ctx, session_info,
4688 p->msg_ctx, r->in.flags,
4689 r->in.server,
4690 r->out.info, r->out.count);
4691 break;
4692 case 1:
4693 result = enumprinters_level1(p->mem_ctx, session_info,
4694 p->msg_ctx, r->in.flags,
4695 r->in.server,
4696 r->out.info, r->out.count);
4697 break;
4698 case 2:
4699 result = enumprinters_level2(p->mem_ctx, session_info,
4700 p->msg_ctx, r->in.flags,
4701 r->in.server,
4702 r->out.info, r->out.count);
4703 break;
4704 case 4:
4705 result = enumprinters_level4(p->mem_ctx, session_info,
4706 p->msg_ctx, r->in.flags,
4707 r->in.server,
4708 r->out.info, r->out.count);
4709 break;
4710 case 5:
4711 result = enumprinters_level5(p->mem_ctx, session_info,
4712 p->msg_ctx, r->in.flags,
4713 r->in.server,
4714 r->out.info, r->out.count);
4715 break;
4716 default:
4717 return WERR_UNKNOWN_LEVEL;
4720 if (!W_ERROR_IS_OK(result)) {
4721 return result;
4724 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4725 spoolss_EnumPrinters,
4726 *r->out.info, r->in.level,
4727 *r->out.count);
4728 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4729 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4731 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4734 /****************************************************************
4735 _spoolss_GetPrinter
4736 ****************************************************************/
4738 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4739 struct spoolss_GetPrinter *r)
4741 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4742 struct spoolss_PrinterInfo2 *info2 = NULL;
4743 WERROR result = WERR_OK;
4744 int snum;
4746 /* that's an [in out] buffer */
4748 if (!r->in.buffer && (r->in.offered != 0)) {
4749 return WERR_INVALID_PARAM;
4752 *r->out.needed = 0;
4754 if (Printer == NULL) {
4755 return WERR_BADFID;
4758 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4759 return WERR_BADFID;
4762 result = winreg_get_printer_internal(p->mem_ctx,
4763 get_session_info_system(),
4764 p->msg_ctx,
4765 lp_const_servicename(snum),
4766 &info2);
4767 if (!W_ERROR_IS_OK(result)) {
4768 goto out;
4771 switch (r->in.level) {
4772 case 0:
4773 result = construct_printer_info0(p->mem_ctx,
4774 get_session_info_system(),
4775 p->msg_ctx,
4776 info2,
4777 Printer->servername,
4778 &r->out.info->info0,
4779 snum);
4780 break;
4781 case 1:
4782 result = construct_printer_info1(p->mem_ctx, info2,
4783 PRINTER_ENUM_ICON8,
4784 Printer->servername,
4785 &r->out.info->info1, snum);
4786 break;
4787 case 2:
4788 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4789 Printer->servername,
4790 &r->out.info->info2, snum);
4791 break;
4792 case 3:
4793 result = construct_printer_info3(p->mem_ctx, info2,
4794 Printer->servername,
4795 &r->out.info->info3, snum);
4796 break;
4797 case 4:
4798 result = construct_printer_info4(p->mem_ctx, info2,
4799 Printer->servername,
4800 &r->out.info->info4, snum);
4801 break;
4802 case 5:
4803 result = construct_printer_info5(p->mem_ctx, info2,
4804 Printer->servername,
4805 &r->out.info->info5, snum);
4806 break;
4807 case 6:
4808 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4809 Printer->servername,
4810 &r->out.info->info6, snum);
4811 break;
4812 case 7:
4813 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4814 Printer->servername,
4815 &r->out.info->info7, snum);
4816 break;
4817 case 8:
4818 result = construct_printer_info8(p->mem_ctx, info2,
4819 Printer->servername,
4820 &r->out.info->info8, snum);
4821 break;
4822 default:
4823 result = WERR_UNKNOWN_LEVEL;
4824 break;
4827 out:
4828 if (!W_ERROR_IS_OK(result)) {
4829 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4830 r->in.level, win_errstr(result)));
4831 TALLOC_FREE(r->out.info);
4832 return result;
4835 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4836 r->out.info, r->in.level);
4837 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4839 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4842 /********************************************************************
4843 ********************************************************************/
4845 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4846 do { \
4847 if (in && strlen(in)) { \
4848 out = talloc_strdup(mem_ctx, in); \
4849 } else { \
4850 out = talloc_strdup(mem_ctx, ""); \
4852 W_ERROR_HAVE_NO_MEMORY(out); \
4853 } while (0);
4855 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4856 do { \
4857 if (in && strlen(in)) { \
4858 out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4859 } else { \
4860 out = talloc_strdup(mem_ctx, ""); \
4862 W_ERROR_HAVE_NO_MEMORY(out); \
4863 } while (0);
4865 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4866 const char **string_array,
4867 const char ***presult,
4868 const char *cservername,
4869 const char *arch,
4870 int version)
4872 int i, num_strings = 0;
4873 const char **array = NULL;
4875 if (string_array == NULL) {
4876 return WERR_INVALID_PARAMETER;
4879 for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4880 const char *str = NULL;
4882 if (cservername == NULL || arch == NULL) {
4883 FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4884 } else {
4885 FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4888 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4889 TALLOC_FREE(array);
4890 return WERR_NOMEM;
4894 if (i > 0) {
4895 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4896 &array, &num_strings);
4899 if (presult) {
4900 *presult = array;
4903 return WERR_OK;
4906 /********************************************************************
4907 * fill a spoolss_DriverInfo1 struct
4908 ********************************************************************/
4910 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4911 struct spoolss_DriverInfo1 *r,
4912 const struct spoolss_DriverInfo8 *driver,
4913 const char *servername)
4915 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4916 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4918 return WERR_OK;
4921 /********************************************************************
4922 * fill a spoolss_DriverInfo2 struct
4923 ********************************************************************/
4925 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4926 struct spoolss_DriverInfo2 *r,
4927 const struct spoolss_DriverInfo8 *driver,
4928 const char *servername)
4931 const char *cservername = canon_servername(servername);
4933 r->version = driver->version;
4935 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4936 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4937 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4938 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4940 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4941 driver->architecture,
4942 driver->version,
4943 driver->driver_path,
4944 r->driver_path);
4946 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4947 driver->architecture,
4948 driver->version,
4949 driver->data_file,
4950 r->data_file);
4952 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4953 driver->architecture,
4954 driver->version,
4955 driver->config_file,
4956 r->config_file);
4958 return WERR_OK;
4961 /********************************************************************
4962 * fill a spoolss_DriverInfo3 struct
4963 ********************************************************************/
4965 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4966 struct spoolss_DriverInfo3 *r,
4967 const struct spoolss_DriverInfo8 *driver,
4968 const char *servername)
4970 const char *cservername = canon_servername(servername);
4972 r->version = driver->version;
4974 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4975 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4976 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4977 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4979 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4980 driver->architecture,
4981 driver->version,
4982 driver->driver_path,
4983 r->driver_path);
4985 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4986 driver->architecture,
4987 driver->version,
4988 driver->data_file,
4989 r->data_file);
4991 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4992 driver->architecture,
4993 driver->version,
4994 driver->config_file,
4995 r->config_file);
4997 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4998 driver->architecture,
4999 driver->version,
5000 driver->help_file,
5001 r->help_file);
5003 FILL_DRIVER_STRING(mem_ctx,
5004 driver->monitor_name,
5005 r->monitor_name);
5007 FILL_DRIVER_STRING(mem_ctx,
5008 driver->default_datatype,
5009 r->default_datatype);
5011 return string_array_from_driver_info(mem_ctx,
5012 driver->dependent_files,
5013 &r->dependent_files,
5014 cservername,
5015 driver->architecture,
5016 driver->version);
5019 /********************************************************************
5020 * fill a spoolss_DriverInfo4 struct
5021 ********************************************************************/
5023 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
5024 struct spoolss_DriverInfo4 *r,
5025 const struct spoolss_DriverInfo8 *driver,
5026 const char *servername)
5028 const char *cservername = canon_servername(servername);
5029 WERROR result;
5031 r->version = driver->version;
5033 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5034 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5035 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5036 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5038 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5039 driver->architecture,
5040 driver->version,
5041 driver->driver_path,
5042 r->driver_path);
5044 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5045 driver->architecture,
5046 driver->version,
5047 driver->data_file,
5048 r->data_file);
5050 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5051 driver->architecture,
5052 driver->version,
5053 driver->config_file,
5054 r->config_file);
5056 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5057 driver->architecture,
5058 driver->version,
5059 driver->help_file,
5060 r->help_file);
5062 result = string_array_from_driver_info(mem_ctx,
5063 driver->dependent_files,
5064 &r->dependent_files,
5065 cservername,
5066 driver->architecture,
5067 driver->version);
5068 if (!W_ERROR_IS_OK(result)) {
5069 return result;
5072 FILL_DRIVER_STRING(mem_ctx,
5073 driver->monitor_name,
5074 r->monitor_name);
5076 FILL_DRIVER_STRING(mem_ctx,
5077 driver->default_datatype,
5078 r->default_datatype);
5081 result = string_array_from_driver_info(mem_ctx,
5082 driver->previous_names,
5083 &r->previous_names,
5084 NULL, NULL, 0);
5086 return result;
5089 /********************************************************************
5090 * fill a spoolss_DriverInfo5 struct
5091 ********************************************************************/
5093 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5094 struct spoolss_DriverInfo5 *r,
5095 const struct spoolss_DriverInfo8 *driver,
5096 const char *servername)
5098 const char *cservername = canon_servername(servername);
5100 r->version = driver->version;
5102 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5103 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5104 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5105 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5107 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5108 driver->architecture,
5109 driver->version,
5110 driver->driver_path,
5111 r->driver_path);
5113 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5114 driver->architecture,
5115 driver->version,
5116 driver->data_file,
5117 r->data_file);
5119 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5120 driver->architecture,
5121 driver->version,
5122 driver->config_file,
5123 r->config_file);
5125 r->driver_attributes = 0;
5126 r->config_version = 0;
5127 r->driver_version = 0;
5129 return WERR_OK;
5131 /********************************************************************
5132 * fill a spoolss_DriverInfo6 struct
5133 ********************************************************************/
5135 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5136 struct spoolss_DriverInfo6 *r,
5137 const struct spoolss_DriverInfo8 *driver,
5138 const char *servername)
5140 const char *cservername = canon_servername(servername);
5141 WERROR result;
5143 r->version = driver->version;
5145 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5146 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5147 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5148 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5150 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5151 driver->architecture,
5152 driver->version,
5153 driver->driver_path,
5154 r->driver_path);
5156 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5157 driver->architecture,
5158 driver->version,
5159 driver->data_file,
5160 r->data_file);
5162 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5163 driver->architecture,
5164 driver->version,
5165 driver->config_file,
5166 r->config_file);
5168 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5169 driver->architecture,
5170 driver->version,
5171 driver->help_file,
5172 r->help_file);
5174 FILL_DRIVER_STRING(mem_ctx,
5175 driver->monitor_name,
5176 r->monitor_name);
5178 FILL_DRIVER_STRING(mem_ctx,
5179 driver->default_datatype,
5180 r->default_datatype);
5182 result = string_array_from_driver_info(mem_ctx,
5183 driver->dependent_files,
5184 &r->dependent_files,
5185 cservername,
5186 driver->architecture,
5187 driver->version);
5188 if (!W_ERROR_IS_OK(result)) {
5189 return result;
5192 result = string_array_from_driver_info(mem_ctx,
5193 driver->previous_names,
5194 &r->previous_names,
5195 NULL, NULL, 0);
5196 if (!W_ERROR_IS_OK(result)) {
5197 return result;
5200 r->driver_date = driver->driver_date;
5201 r->driver_version = driver->driver_version;
5203 FILL_DRIVER_STRING(mem_ctx,
5204 driver->manufacturer_name,
5205 r->manufacturer_name);
5206 FILL_DRIVER_STRING(mem_ctx,
5207 driver->manufacturer_url,
5208 r->manufacturer_url);
5209 FILL_DRIVER_STRING(mem_ctx,
5210 driver->hardware_id,
5211 r->hardware_id);
5212 FILL_DRIVER_STRING(mem_ctx,
5213 driver->provider,
5214 r->provider);
5216 return WERR_OK;
5219 /********************************************************************
5220 * fill a spoolss_DriverInfo8 struct
5221 ********************************************************************/
5223 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5224 struct spoolss_DriverInfo8 *r,
5225 const struct spoolss_DriverInfo8 *driver,
5226 const char *servername)
5228 const char *cservername = canon_servername(servername);
5229 WERROR result;
5231 r->version = driver->version;
5233 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5234 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5235 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5236 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5238 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5239 driver->architecture,
5240 driver->version,
5241 driver->driver_path,
5242 r->driver_path);
5244 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5245 driver->architecture,
5246 driver->version,
5247 driver->data_file,
5248 r->data_file);
5250 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5251 driver->architecture,
5252 driver->version,
5253 driver->config_file,
5254 r->config_file);
5256 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5257 driver->architecture,
5258 driver->version,
5259 driver->help_file,
5260 r->help_file);
5262 FILL_DRIVER_STRING(mem_ctx,
5263 driver->monitor_name,
5264 r->monitor_name);
5266 FILL_DRIVER_STRING(mem_ctx,
5267 driver->default_datatype,
5268 r->default_datatype);
5270 result = string_array_from_driver_info(mem_ctx,
5271 driver->dependent_files,
5272 &r->dependent_files,
5273 cservername,
5274 driver->architecture,
5275 driver->version);
5276 if (!W_ERROR_IS_OK(result)) {
5277 return result;
5280 result = string_array_from_driver_info(mem_ctx,
5281 driver->previous_names,
5282 &r->previous_names,
5283 NULL, NULL, 0);
5284 if (!W_ERROR_IS_OK(result)) {
5285 return result;
5288 r->driver_date = driver->driver_date;
5289 r->driver_version = driver->driver_version;
5291 FILL_DRIVER_STRING(mem_ctx,
5292 driver->manufacturer_name,
5293 r->manufacturer_name);
5294 FILL_DRIVER_STRING(mem_ctx,
5295 driver->manufacturer_url,
5296 r->manufacturer_url);
5297 FILL_DRIVER_STRING(mem_ctx,
5298 driver->hardware_id,
5299 r->hardware_id);
5300 FILL_DRIVER_STRING(mem_ctx,
5301 driver->provider,
5302 r->provider);
5304 FILL_DRIVER_STRING(mem_ctx,
5305 driver->print_processor,
5306 r->print_processor);
5307 FILL_DRIVER_STRING(mem_ctx,
5308 driver->vendor_setup,
5309 r->vendor_setup);
5311 result = string_array_from_driver_info(mem_ctx,
5312 driver->color_profiles,
5313 &r->color_profiles,
5314 NULL, NULL, 0);
5315 if (!W_ERROR_IS_OK(result)) {
5316 return result;
5319 FILL_DRIVER_STRING(mem_ctx,
5320 driver->inf_path,
5321 r->inf_path);
5323 r->printer_driver_attributes = driver->printer_driver_attributes;
5325 result = string_array_from_driver_info(mem_ctx,
5326 driver->core_driver_dependencies,
5327 &r->core_driver_dependencies,
5328 NULL, NULL, 0);
5329 if (!W_ERROR_IS_OK(result)) {
5330 return result;
5333 r->min_inbox_driver_ver_date = driver->min_inbox_driver_ver_date;
5334 r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5336 return WERR_OK;
5339 #if 0 /* disabled until marshalling issues are resolved - gd */
5340 /********************************************************************
5341 ********************************************************************/
5343 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5344 struct spoolss_DriverFileInfo *r,
5345 const char *cservername,
5346 const char *file_name,
5347 enum spoolss_DriverFileType file_type,
5348 uint32_t file_version)
5350 r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
5351 cservername, file_name);
5352 W_ERROR_HAVE_NO_MEMORY(r->file_name);
5353 r->file_type = file_type;
5354 r->file_version = file_version;
5356 return WERR_OK;
5359 /********************************************************************
5360 ********************************************************************/
5362 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5363 const struct spoolss_DriverInfo8 *driver,
5364 const char *cservername,
5365 struct spoolss_DriverFileInfo **info_p,
5366 uint32_t *count_p)
5368 struct spoolss_DriverFileInfo *info = NULL;
5369 uint32_t count = 0;
5370 WERROR result;
5371 uint32_t i;
5373 *info_p = NULL;
5374 *count_p = 0;
5376 if (strlen(driver->driver_path)) {
5377 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5378 struct spoolss_DriverFileInfo,
5379 count + 1);
5380 W_ERROR_HAVE_NO_MEMORY(info);
5381 result = fill_spoolss_DriverFileInfo(info,
5382 &info[count],
5383 cservername,
5384 driver->driver_path,
5385 SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5387 W_ERROR_NOT_OK_RETURN(result);
5388 count++;
5391 if (strlen(driver->config_file)) {
5392 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5393 struct spoolss_DriverFileInfo,
5394 count + 1);
5395 W_ERROR_HAVE_NO_MEMORY(info);
5396 result = fill_spoolss_DriverFileInfo(info,
5397 &info[count],
5398 cservername,
5399 driver->config_file,
5400 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5402 W_ERROR_NOT_OK_RETURN(result);
5403 count++;
5406 if (strlen(driver->data_file)) {
5407 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5408 struct spoolss_DriverFileInfo,
5409 count + 1);
5410 W_ERROR_HAVE_NO_MEMORY(info);
5411 result = fill_spoolss_DriverFileInfo(info,
5412 &info[count],
5413 cservername,
5414 driver->data_file,
5415 SPOOLSS_DRIVER_FILE_TYPE_DATA,
5417 W_ERROR_NOT_OK_RETURN(result);
5418 count++;
5421 if (strlen(driver->help_file)) {
5422 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5423 struct spoolss_DriverFileInfo,
5424 count + 1);
5425 W_ERROR_HAVE_NO_MEMORY(info);
5426 result = fill_spoolss_DriverFileInfo(info,
5427 &info[count],
5428 cservername,
5429 driver->help_file,
5430 SPOOLSS_DRIVER_FILE_TYPE_HELP,
5432 W_ERROR_NOT_OK_RETURN(result);
5433 count++;
5436 for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5437 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5438 struct spoolss_DriverFileInfo,
5439 count + 1);
5440 W_ERROR_HAVE_NO_MEMORY(info);
5441 result = fill_spoolss_DriverFileInfo(info,
5442 &info[count],
5443 cservername,
5444 driver->dependent_files[i],
5445 SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5447 W_ERROR_NOT_OK_RETURN(result);
5448 count++;
5451 *info_p = info;
5452 *count_p = count;
5454 return WERR_OK;
5457 /********************************************************************
5458 * fill a spoolss_DriverInfo101 struct
5459 ********************************************************************/
5461 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5462 struct spoolss_DriverInfo101 *r,
5463 const struct spoolss_DriverInfo8 *driver,
5464 const char *servername)
5466 const char *cservername = canon_servername(servername);
5467 WERROR result;
5469 r->version = driver->version;
5471 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5472 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5473 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5474 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5476 result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5477 cservername,
5478 &r->file_info,
5479 &r->file_count);
5480 if (!W_ERROR_IS_OK(result)) {
5481 return result;
5484 FILL_DRIVER_STRING(mem_ctx,
5485 driver->monitor_name,
5486 r->monitor_name);
5488 FILL_DRIVER_STRING(mem_ctx,
5489 driver->default_datatype,
5490 r->default_datatype);
5492 result = string_array_from_driver_info(mem_ctx,
5493 driver->previous_names,
5494 &r->previous_names,
5495 NULL, NULL, 0);
5496 if (!W_ERROR_IS_OK(result)) {
5497 return result;
5500 r->driver_date = driver->driver_date;
5501 r->driver_version = driver->driver_version;
5503 FILL_DRIVER_STRING(mem_ctx,
5504 driver->manufacturer_name,
5505 r->manufacturer_name);
5506 FILL_DRIVER_STRING(mem_ctx,
5507 driver->manufacturer_url,
5508 r->manufacturer_url);
5509 FILL_DRIVER_STRING(mem_ctx,
5510 driver->hardware_id,
5511 r->hardware_id);
5512 FILL_DRIVER_STRING(mem_ctx,
5513 driver->provider,
5514 r->provider);
5516 return WERR_OK;
5518 #endif
5519 /********************************************************************
5520 ********************************************************************/
5522 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5523 const struct auth_serversupplied_info *session_info,
5524 struct messaging_context *msg_ctx,
5525 uint32_t level,
5526 union spoolss_DriverInfo *r,
5527 int snum,
5528 const char *servername,
5529 const char *architecture,
5530 uint32_t version)
5532 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5533 struct spoolss_DriverInfo8 *driver;
5534 WERROR result;
5535 struct dcerpc_binding_handle *b;
5537 if (level == 101) {
5538 return WERR_UNKNOWN_LEVEL;
5541 result = winreg_printer_binding_handle(mem_ctx,
5542 session_info,
5543 msg_ctx,
5544 &b);
5545 if (!W_ERROR_IS_OK(result)) {
5546 return result;
5549 result = winreg_get_printer(mem_ctx, b,
5550 lp_const_servicename(snum),
5551 &pinfo2);
5553 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5554 win_errstr(result)));
5556 if (!W_ERROR_IS_OK(result)) {
5557 return WERR_INVALID_PRINTER_NAME;
5560 result = winreg_get_driver(mem_ctx, b,
5561 architecture,
5562 pinfo2->drivername, version, &driver);
5564 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5565 win_errstr(result)));
5567 if (!W_ERROR_IS_OK(result)) {
5569 * Is this a W2k client ?
5572 if (version < 3) {
5573 talloc_free(pinfo2);
5574 return WERR_UNKNOWN_PRINTER_DRIVER;
5577 /* Yes - try again with a WinNT driver. */
5578 version = 2;
5579 result = winreg_get_driver(mem_ctx, b,
5580 architecture,
5581 pinfo2->drivername,
5582 version, &driver);
5583 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5584 win_errstr(result)));
5585 if (!W_ERROR_IS_OK(result)) {
5586 talloc_free(pinfo2);
5587 return WERR_UNKNOWN_PRINTER_DRIVER;
5591 switch (level) {
5592 case 1:
5593 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5594 break;
5595 case 2:
5596 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5597 break;
5598 case 3:
5599 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5600 break;
5601 case 4:
5602 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5603 break;
5604 case 5:
5605 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5606 break;
5607 case 6:
5608 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5609 break;
5610 case 8:
5611 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5612 break;
5613 #if 0 /* disabled until marshalling issues are resolved - gd */
5614 case 101:
5615 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5616 break;
5617 #endif
5618 default:
5619 result = WERR_UNKNOWN_LEVEL;
5620 break;
5623 talloc_free(pinfo2);
5624 talloc_free(driver);
5626 return result;
5629 /****************************************************************
5630 _spoolss_GetPrinterDriver2
5631 ****************************************************************/
5633 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5634 struct spoolss_GetPrinterDriver2 *r)
5636 struct printer_handle *printer;
5637 WERROR result;
5639 int snum;
5641 /* that's an [in out] buffer */
5643 if (!r->in.buffer && (r->in.offered != 0)) {
5644 return WERR_INVALID_PARAM;
5647 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5649 if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5650 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5651 return WERR_INVALID_PRINTER_NAME;
5654 *r->out.needed = 0;
5655 *r->out.server_major_version = 0;
5656 *r->out.server_minor_version = 0;
5658 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5659 return WERR_BADFID;
5662 result = construct_printer_driver_info_level(p->mem_ctx,
5663 get_session_info_system(),
5664 p->msg_ctx,
5665 r->in.level, r->out.info,
5666 snum, printer->servername,
5667 r->in.architecture,
5668 r->in.client_major_version);
5669 if (!W_ERROR_IS_OK(result)) {
5670 TALLOC_FREE(r->out.info);
5671 return result;
5674 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5675 r->out.info, r->in.level);
5676 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5678 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5682 /****************************************************************
5683 _spoolss_StartPagePrinter
5684 ****************************************************************/
5686 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5687 struct spoolss_StartPagePrinter *r)
5689 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5691 if (!Printer) {
5692 DEBUG(3,("_spoolss_StartPagePrinter: "
5693 "Error in startpageprinter printer handle\n"));
5694 return WERR_BADFID;
5697 Printer->page_started = true;
5698 return WERR_OK;
5701 /****************************************************************
5702 _spoolss_EndPagePrinter
5703 ****************************************************************/
5705 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5706 struct spoolss_EndPagePrinter *r)
5708 int snum;
5710 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5712 if (!Printer) {
5713 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5714 OUR_HANDLE(r->in.handle)));
5715 return WERR_BADFID;
5718 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5719 return WERR_BADFID;
5721 Printer->page_started = false;
5722 print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5724 return WERR_OK;
5727 /****************************************************************
5728 _spoolss_StartDocPrinter
5729 ****************************************************************/
5731 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5732 struct spoolss_StartDocPrinter *r)
5734 struct spoolss_DocumentInfo1 *info_1;
5735 int snum;
5736 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5737 WERROR werr;
5739 if (!Printer) {
5740 DEBUG(2,("_spoolss_StartDocPrinter: "
5741 "Invalid handle (%s:%u:%u)\n",
5742 OUR_HANDLE(r->in.handle)));
5743 return WERR_BADFID;
5746 if (Printer->jobid) {
5747 DEBUG(2, ("_spoolss_StartDocPrinter: "
5748 "StartDocPrinter called twice! "
5749 "(existing jobid = %d)\n", Printer->jobid));
5750 return WERR_INVALID_HANDLE;
5753 if (r->in.level != 1) {
5754 return WERR_UNKNOWN_LEVEL;
5757 info_1 = r->in.info.info1;
5760 * a nice thing with NT is it doesn't listen to what you tell it.
5761 * when asked to send _only_ RAW datas, it tries to send datas
5762 * in EMF format.
5764 * So I add checks like in NT Server ...
5767 if (info_1->datatype) {
5768 if (strcmp(info_1->datatype, "RAW") != 0) {
5769 *r->out.job_id = 0;
5770 return WERR_INVALID_DATATYPE;
5774 /* get the share number of the printer */
5775 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5776 return WERR_BADFID;
5779 werr = print_job_start(p->session_info,
5780 p->msg_ctx,
5781 p->client_id->name,
5782 snum,
5783 info_1->document_name,
5784 info_1->output_file,
5785 Printer->devmode,
5786 &Printer->jobid);
5788 /* An error occured in print_job_start() so return an appropriate
5789 NT error code. */
5791 if (!W_ERROR_IS_OK(werr)) {
5792 return werr;
5795 Printer->document_started = true;
5796 *r->out.job_id = Printer->jobid;
5798 return WERR_OK;
5801 /****************************************************************
5802 _spoolss_EndDocPrinter
5803 ****************************************************************/
5805 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5806 struct spoolss_EndDocPrinter *r)
5808 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5809 NTSTATUS status;
5810 int snum;
5812 if (!Printer) {
5813 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5814 OUR_HANDLE(r->in.handle)));
5815 return WERR_BADFID;
5818 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5819 return WERR_BADFID;
5822 Printer->document_started = false;
5823 status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5824 if (!NT_STATUS_IS_OK(status)) {
5825 DEBUG(2, ("_spoolss_EndDocPrinter: "
5826 "print_job_end failed [%s]\n",
5827 nt_errstr(status)));
5830 Printer->jobid = 0;
5831 return ntstatus_to_werror(status);
5834 /****************************************************************
5835 _spoolss_WritePrinter
5836 ****************************************************************/
5838 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5839 struct spoolss_WritePrinter *r)
5841 ssize_t buffer_written;
5842 int snum;
5843 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5845 if (!Printer) {
5846 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5847 OUR_HANDLE(r->in.handle)));
5848 *r->out.num_written = r->in._data_size;
5849 return WERR_BADFID;
5852 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5853 return WERR_BADFID;
5855 /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5856 buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5857 snum, Printer->jobid,
5858 (const char *)r->in.data.data,
5859 (size_t)r->in._data_size);
5860 if (buffer_written == (ssize_t)-1) {
5861 *r->out.num_written = 0;
5862 if (errno == ENOSPC)
5863 return WERR_NO_SPOOL_SPACE;
5864 else
5865 return WERR_ACCESS_DENIED;
5868 *r->out.num_written = r->in._data_size;
5870 return WERR_OK;
5873 /********************************************************************
5874 * api_spoolss_getprinter
5875 * called from the spoolss dispatcher
5877 ********************************************************************/
5879 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5880 struct pipes_struct *p)
5882 const struct auth_serversupplied_info *session_info = p->session_info;
5883 int snum;
5884 WERROR errcode = WERR_BADFUNC;
5885 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5887 if (!Printer) {
5888 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5889 OUR_HANDLE(handle)));
5890 return WERR_BADFID;
5893 if (!get_printer_snum(p, handle, &snum, NULL))
5894 return WERR_BADFID;
5896 switch (command) {
5897 case SPOOLSS_PRINTER_CONTROL_PAUSE:
5898 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
5899 break;
5900 case SPOOLSS_PRINTER_CONTROL_RESUME:
5901 case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5902 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
5903 break;
5904 case SPOOLSS_PRINTER_CONTROL_PURGE:
5905 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
5906 break;
5907 default:
5908 return WERR_UNKNOWN_LEVEL;
5911 return errcode;
5915 /****************************************************************
5916 _spoolss_AbortPrinter
5917 * From MSDN: "Deletes printer's spool file if printer is configured
5918 * for spooling"
5919 ****************************************************************/
5921 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
5922 struct spoolss_AbortPrinter *r)
5924 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5925 int snum;
5926 WERROR errcode = WERR_OK;
5928 if (!Printer) {
5929 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5930 OUR_HANDLE(r->in.handle)));
5931 return WERR_BADFID;
5934 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5935 return WERR_BADFID;
5937 if (!Printer->document_started) {
5938 return WERR_SPL_NO_STARTDOC;
5941 errcode = print_job_delete(p->session_info,
5942 p->msg_ctx,
5943 snum,
5944 Printer->jobid);
5946 return errcode;
5949 /********************************************************************
5950 * called by spoolss_api_setprinter
5951 * when updating a printer description
5952 ********************************************************************/
5954 static WERROR update_printer_sec(struct policy_handle *handle,
5955 struct pipes_struct *p,
5956 struct sec_desc_buf *secdesc_ctr)
5958 struct spoolss_security_descriptor *new_secdesc = NULL;
5959 struct spoolss_security_descriptor *old_secdesc = NULL;
5960 const char *printer;
5961 WERROR result;
5962 int snum;
5963 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5964 struct dcerpc_binding_handle *b;
5966 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5967 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5968 OUR_HANDLE(handle)));
5970 result = WERR_BADFID;
5971 goto done;
5974 if (secdesc_ctr == NULL) {
5975 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5976 result = WERR_INVALID_PARAM;
5977 goto done;
5979 printer = lp_const_servicename(snum);
5981 /* Check the user has permissions to change the security
5982 descriptor. By experimentation with two NT machines, the user
5983 requires Full Access to the printer to change security
5984 information. */
5986 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5987 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5988 result = WERR_ACCESS_DENIED;
5989 goto done;
5992 result = winreg_printer_binding_handle(p->mem_ctx,
5993 get_session_info_system(),
5994 p->msg_ctx,
5995 &b);
5996 if (!W_ERROR_IS_OK(result)) {
5997 goto done;
6000 /* NT seems to like setting the security descriptor even though
6001 nothing may have actually changed. */
6002 result = winreg_get_printer_secdesc(p->mem_ctx, b,
6003 printer,
6004 &old_secdesc);
6005 if (!W_ERROR_IS_OK(result)) {
6006 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
6007 result = WERR_BADFID;
6008 goto done;
6011 if (DEBUGLEVEL >= 10) {
6012 struct security_acl *the_acl;
6013 int i;
6015 the_acl = old_secdesc->dacl;
6016 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6017 printer, the_acl->num_aces));
6019 for (i = 0; i < the_acl->num_aces; i++) {
6020 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6021 &the_acl->aces[i].trustee),
6022 the_acl->aces[i].access_mask));
6025 the_acl = secdesc_ctr->sd->dacl;
6027 if (the_acl) {
6028 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6029 printer, the_acl->num_aces));
6031 for (i = 0; i < the_acl->num_aces; i++) {
6032 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6033 &the_acl->aces[i].trustee),
6034 the_acl->aces[i].access_mask));
6036 } else {
6037 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6041 new_secdesc = sec_desc_merge(p->mem_ctx, secdesc_ctr->sd, old_secdesc);
6042 if (new_secdesc == NULL) {
6043 result = WERR_NOMEM;
6044 goto done;
6047 if (security_descriptor_equal(new_secdesc, old_secdesc)) {
6048 result = WERR_OK;
6049 goto done;
6052 result = winreg_set_printer_secdesc(p->mem_ctx, b,
6053 printer,
6054 new_secdesc);
6056 done:
6057 return result;
6060 /********************************************************************
6061 Canonicalize printer info from a client
6062 ********************************************************************/
6064 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
6065 struct spoolss_SetPrinterInfo2 *info2,
6066 int snum)
6068 fstring printername;
6069 const char *p;
6071 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6072 "portname=%s drivername=%s comment=%s location=%s\n",
6073 info2->servername, info2->printername, info2->sharename,
6074 info2->portname, info2->drivername, info2->comment,
6075 info2->location));
6077 /* we force some elements to "correct" values */
6078 info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
6079 if (info2->servername == NULL) {
6080 return false;
6082 info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6083 if (info2->sharename == NULL) {
6084 return false;
6087 /* check to see if we allow printername != sharename */
6088 if (lp_force_printername(snum)) {
6089 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6090 global_myname(), info2->sharename);
6091 } else {
6092 /* make sure printername is in \\server\printername format */
6093 fstrcpy(printername, info2->printername);
6094 p = printername;
6095 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6096 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6097 p++;
6100 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6101 global_myname(), p);
6103 if (info2->printername == NULL) {
6104 return false;
6107 info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6108 info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6110 return true;
6113 /****************************************************************************
6114 ****************************************************************************/
6116 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6118 char *cmd = lp_addport_cmd();
6119 char *command = NULL;
6120 int ret;
6121 bool is_print_op = false;
6123 if ( !*cmd ) {
6124 return WERR_ACCESS_DENIED;
6127 command = talloc_asprintf(ctx,
6128 "%s \"%s\" \"%s\"", cmd, portname, uri );
6129 if (!command) {
6130 return WERR_NOMEM;
6133 if ( token )
6134 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6136 DEBUG(10,("Running [%s]\n", command));
6138 /********* BEGIN SePrintOperatorPrivilege **********/
6140 if ( is_print_op )
6141 become_root();
6143 ret = smbrun(command, NULL);
6145 if ( is_print_op )
6146 unbecome_root();
6148 /********* END SePrintOperatorPrivilege **********/
6150 DEBUGADD(10,("returned [%d]\n", ret));
6152 TALLOC_FREE(command);
6154 if ( ret != 0 ) {
6155 return WERR_ACCESS_DENIED;
6158 return WERR_OK;
6161 /****************************************************************************
6162 ****************************************************************************/
6164 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6165 struct spoolss_SetPrinterInfo2 *info2,
6166 const char *remote_machine,
6167 struct messaging_context *msg_ctx)
6169 char *cmd = lp_addprinter_cmd();
6170 char **qlines;
6171 char *command = NULL;
6172 int numlines;
6173 int ret;
6174 int fd;
6175 bool is_print_op = false;
6177 if (!remote_machine) {
6178 return false;
6181 command = talloc_asprintf(ctx,
6182 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6183 cmd, info2->printername, info2->sharename,
6184 info2->portname, info2->drivername,
6185 info2->location, info2->comment, remote_machine);
6186 if (!command) {
6187 return false;
6190 if ( token )
6191 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6193 DEBUG(10,("Running [%s]\n", command));
6195 /********* BEGIN SePrintOperatorPrivilege **********/
6197 if ( is_print_op )
6198 become_root();
6200 if ( (ret = smbrun(command, &fd)) == 0 ) {
6201 /* Tell everyone we updated smb.conf. */
6202 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6205 if ( is_print_op )
6206 unbecome_root();
6208 /********* END SePrintOperatorPrivilege **********/
6210 DEBUGADD(10,("returned [%d]\n", ret));
6212 TALLOC_FREE(command);
6214 if ( ret != 0 ) {
6215 if (fd != -1)
6216 close(fd);
6217 return false;
6220 /* reload our services immediately */
6221 become_root();
6222 reload_services(msg_ctx, -1, false);
6223 unbecome_root();
6225 numlines = 0;
6226 /* Get lines and convert them back to dos-codepage */
6227 qlines = fd_lines_load(fd, &numlines, 0, NULL);
6228 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6229 close(fd);
6231 /* Set the portname to what the script says the portname should be. */
6232 /* but don't require anything to be return from the script exit a good error code */
6234 if (numlines) {
6235 /* Set the portname to what the script says the portname should be. */
6236 info2->portname = talloc_strdup(ctx, qlines[0]);
6237 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6240 TALLOC_FREE(qlines);
6241 return true;
6244 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6245 const struct auth_serversupplied_info *session_info,
6246 struct messaging_context *msg_ctx,
6247 int snum,
6248 struct spoolss_SetPrinterInfo2 *printer,
6249 struct spoolss_PrinterInfo2 *old_printer)
6251 bool force_update = (old_printer == NULL);
6252 const char *dnsdomname;
6253 const char *longname;
6254 const char *uncname;
6255 const char *spooling;
6256 DATA_BLOB buffer;
6257 WERROR result = WERR_OK;
6258 struct dcerpc_binding_handle *b;
6260 result = winreg_printer_binding_handle(mem_ctx,
6261 session_info,
6262 msg_ctx,
6263 &b);
6264 if (!W_ERROR_IS_OK(result)) {
6265 return result;
6268 if (force_update || !strequal(printer->drivername, old_printer->drivername)) {
6269 push_reg_sz(mem_ctx, &buffer, printer->drivername);
6270 winreg_set_printer_dataex(mem_ctx, b,
6271 printer->sharename,
6272 SPOOL_DSSPOOLER_KEY,
6273 SPOOL_REG_DRIVERNAME,
6274 REG_SZ,
6275 buffer.data,
6276 buffer.length);
6278 if (!force_update) {
6279 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6280 printer->drivername));
6282 notify_printer_driver(server_event_context(), msg_ctx,
6283 snum, printer->drivername ?
6284 printer->drivername : "");
6288 if (force_update || !strequal(printer->comment, old_printer->comment)) {
6289 push_reg_sz(mem_ctx, &buffer, printer->comment);
6290 winreg_set_printer_dataex(mem_ctx, b,
6291 printer->sharename,
6292 SPOOL_DSSPOOLER_KEY,
6293 SPOOL_REG_DESCRIPTION,
6294 REG_SZ,
6295 buffer.data,
6296 buffer.length);
6298 if (!force_update) {
6299 notify_printer_comment(server_event_context(), msg_ctx,
6300 snum, printer->comment ?
6301 printer->comment : "");
6305 if (force_update || !strequal(printer->sharename, old_printer->sharename)) {
6306 push_reg_sz(mem_ctx, &buffer, printer->sharename);
6307 winreg_set_printer_dataex(mem_ctx, b,
6308 printer->sharename,
6309 SPOOL_DSSPOOLER_KEY,
6310 SPOOL_REG_PRINTSHARENAME,
6311 REG_SZ,
6312 buffer.data,
6313 buffer.length);
6315 if (!force_update) {
6316 notify_printer_sharename(server_event_context(),
6317 msg_ctx,
6318 snum, printer->sharename ?
6319 printer->sharename : "");
6323 if (force_update || !strequal(printer->printername, old_printer->printername)) {
6324 const char *p;
6326 p = strrchr(printer->printername, '\\' );
6327 if (p != NULL) {
6328 p++;
6329 } else {
6330 p = printer->printername;
6333 push_reg_sz(mem_ctx, &buffer, p);
6334 winreg_set_printer_dataex(mem_ctx, b,
6335 printer->sharename,
6336 SPOOL_DSSPOOLER_KEY,
6337 SPOOL_REG_PRINTERNAME,
6338 REG_SZ,
6339 buffer.data,
6340 buffer.length);
6342 if (!force_update) {
6343 notify_printer_printername(server_event_context(),
6344 msg_ctx, snum, p ? p : "");
6348 if (force_update || !strequal(printer->portname, old_printer->portname)) {
6349 push_reg_sz(mem_ctx, &buffer, printer->portname);
6350 winreg_set_printer_dataex(mem_ctx, b,
6351 printer->sharename,
6352 SPOOL_DSSPOOLER_KEY,
6353 SPOOL_REG_PORTNAME,
6354 REG_SZ,
6355 buffer.data,
6356 buffer.length);
6358 if (!force_update) {
6359 notify_printer_port(server_event_context(),
6360 msg_ctx, snum, printer->portname ?
6361 printer->portname : "");
6365 if (force_update || !strequal(printer->location, old_printer->location)) {
6366 push_reg_sz(mem_ctx, &buffer, printer->location);
6367 winreg_set_printer_dataex(mem_ctx, b,
6368 printer->sharename,
6369 SPOOL_DSSPOOLER_KEY,
6370 SPOOL_REG_LOCATION,
6371 REG_SZ,
6372 buffer.data,
6373 buffer.length);
6375 if (!force_update) {
6376 notify_printer_location(server_event_context(),
6377 msg_ctx, snum,
6378 printer->location ?
6379 printer->location : "");
6383 if (force_update || !strequal(printer->sepfile, old_printer->sepfile)) {
6384 push_reg_sz(mem_ctx, &buffer, printer->sepfile);
6385 winreg_set_printer_dataex(mem_ctx, b,
6386 printer->sharename,
6387 SPOOL_DSSPOOLER_KEY,
6388 SPOOL_REG_PRINTSEPARATORFILE,
6389 REG_SZ,
6390 buffer.data,
6391 buffer.length);
6393 if (!force_update) {
6394 notify_printer_sepfile(server_event_context(),
6395 msg_ctx, snum,
6396 printer->sepfile ?
6397 printer->sepfile : "");
6401 if (force_update || printer->starttime != old_printer->starttime) {
6402 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6403 SIVAL(buffer.data, 0, printer->starttime);
6404 winreg_set_printer_dataex(mem_ctx, b,
6405 printer->sharename,
6406 SPOOL_DSSPOOLER_KEY,
6407 SPOOL_REG_PRINTSTARTTIME,
6408 REG_DWORD,
6409 buffer.data,
6410 buffer.length);
6413 if (force_update || printer->untiltime != old_printer->untiltime) {
6414 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6415 SIVAL(buffer.data, 0, printer->untiltime);
6416 winreg_set_printer_dataex(mem_ctx, b,
6417 printer->sharename,
6418 SPOOL_DSSPOOLER_KEY,
6419 SPOOL_REG_PRINTENDTIME,
6420 REG_DWORD,
6421 buffer.data,
6422 buffer.length);
6425 if (force_update || printer->priority != old_printer->priority) {
6426 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6427 SIVAL(buffer.data, 0, printer->priority);
6428 winreg_set_printer_dataex(mem_ctx, b,
6429 printer->sharename,
6430 SPOOL_DSSPOOLER_KEY,
6431 SPOOL_REG_PRIORITY,
6432 REG_DWORD,
6433 buffer.data,
6434 buffer.length);
6437 if (force_update || printer->attributes != old_printer->attributes) {
6438 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6439 SIVAL(buffer.data, 0, (printer->attributes &
6440 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6441 winreg_set_printer_dataex(mem_ctx, b,
6442 printer->sharename,
6443 SPOOL_DSSPOOLER_KEY,
6444 SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6445 REG_DWORD,
6446 buffer.data,
6447 buffer.length);
6449 switch (printer->attributes & 0x3) {
6450 case 0:
6451 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6452 break;
6453 case 1:
6454 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6455 break;
6456 case 2:
6457 spooling = SPOOL_REGVAL_PRINTDIRECT;
6458 break;
6459 default:
6460 spooling = "unknown";
6462 push_reg_sz(mem_ctx, &buffer, spooling);
6463 winreg_set_printer_dataex(mem_ctx, b,
6464 printer->sharename,
6465 SPOOL_DSSPOOLER_KEY,
6466 SPOOL_REG_PRINTSPOOLING,
6467 REG_SZ,
6468 buffer.data,
6469 buffer.length);
6472 push_reg_sz(mem_ctx, &buffer, global_myname());
6473 winreg_set_printer_dataex(mem_ctx, b,
6474 printer->sharename,
6475 SPOOL_DSSPOOLER_KEY,
6476 SPOOL_REG_SHORTSERVERNAME,
6477 REG_SZ,
6478 buffer.data,
6479 buffer.length);
6481 dnsdomname = get_mydnsfullname();
6482 if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6483 longname = talloc_strdup(mem_ctx, dnsdomname);
6484 } else {
6485 longname = talloc_strdup(mem_ctx, global_myname());
6487 if (longname == NULL) {
6488 result = WERR_NOMEM;
6489 goto done;
6492 push_reg_sz(mem_ctx, &buffer, longname);
6493 winreg_set_printer_dataex(mem_ctx, b,
6494 printer->sharename,
6495 SPOOL_DSSPOOLER_KEY,
6496 SPOOL_REG_SERVERNAME,
6497 REG_SZ,
6498 buffer.data,
6499 buffer.length);
6501 uncname = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6502 global_myname(), printer->sharename);
6503 push_reg_sz(mem_ctx, &buffer, uncname);
6504 winreg_set_printer_dataex(mem_ctx, b,
6505 printer->sharename,
6506 SPOOL_DSSPOOLER_KEY,
6507 SPOOL_REG_UNCNAME,
6508 REG_SZ,
6509 buffer.data,
6510 buffer.length);
6512 done:
6513 return result;
6516 /********************************************************************
6517 * Called by spoolss_api_setprinter
6518 * when updating a printer description.
6519 ********************************************************************/
6521 static WERROR update_printer(struct pipes_struct *p,
6522 struct policy_handle *handle,
6523 struct spoolss_SetPrinterInfoCtr *info_ctr,
6524 struct spoolss_DeviceMode *devmode)
6526 uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6527 struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6528 struct spoolss_PrinterInfo2 *old_printer;
6529 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6530 int snum;
6531 WERROR result = WERR_OK;
6532 TALLOC_CTX *tmp_ctx;
6533 struct dcerpc_binding_handle *b;
6535 DEBUG(8,("update_printer\n"));
6537 tmp_ctx = talloc_new(p->mem_ctx);
6538 if (tmp_ctx == NULL) {
6539 return WERR_NOMEM;
6542 if (!Printer) {
6543 result = WERR_BADFID;
6544 goto done;
6547 if (!get_printer_snum(p, handle, &snum, NULL)) {
6548 result = WERR_BADFID;
6549 goto done;
6552 result = winreg_printer_binding_handle(tmp_ctx,
6553 get_session_info_system(),
6554 p->msg_ctx,
6555 &b);
6556 if (!W_ERROR_IS_OK(result)) {
6557 goto done;
6560 result = winreg_get_printer(tmp_ctx, b,
6561 lp_const_servicename(snum),
6562 &old_printer);
6563 if (!W_ERROR_IS_OK(result)) {
6564 result = WERR_BADFID;
6565 goto done;
6568 /* Do sanity check on the requested changes for Samba */
6569 if (!check_printer_ok(tmp_ctx, printer, snum)) {
6570 result = WERR_INVALID_PARAM;
6571 goto done;
6574 /* FIXME!!! If the driver has changed we really should verify that
6575 it is installed before doing much else --jerry */
6577 /* Check calling user has permission to update printer description */
6578 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6579 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6580 result = WERR_ACCESS_DENIED;
6581 goto done;
6584 /* Call addprinter hook */
6585 /* Check changes to see if this is really needed */
6587 if (*lp_addprinter_cmd() &&
6588 (!strequal(printer->drivername, old_printer->drivername) ||
6589 !strequal(printer->comment, old_printer->comment) ||
6590 !strequal(printer->portname, old_printer->portname) ||
6591 !strequal(printer->location, old_printer->location)) )
6593 /* add_printer_hook() will call reload_services() */
6594 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6595 printer, p->client_id->addr,
6596 p->msg_ctx)) {
6597 result = WERR_ACCESS_DENIED;
6598 goto done;
6602 update_dsspooler(tmp_ctx,
6603 get_session_info_system(),
6604 p->msg_ctx,
6605 snum,
6606 printer,
6607 old_printer);
6609 printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6611 if (devmode == NULL) {
6612 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6614 result = winreg_update_printer(tmp_ctx, b,
6615 printer->sharename,
6616 printer_mask,
6617 printer,
6618 devmode,
6619 NULL);
6621 done:
6622 talloc_free(tmp_ctx);
6624 return result;
6627 /****************************************************************************
6628 ****************************************************************************/
6629 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6630 struct policy_handle *handle,
6631 struct spoolss_SetPrinterInfo7 *info7)
6633 #ifdef HAVE_ADS
6634 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6635 WERROR result;
6636 int snum;
6637 struct printer_handle *Printer;
6639 if ( lp_security() != SEC_ADS ) {
6640 return WERR_UNKNOWN_LEVEL;
6643 Printer = find_printer_index_by_hnd(p, handle);
6645 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6647 if (!Printer)
6648 return WERR_BADFID;
6650 if (!get_printer_snum(p, handle, &snum, NULL))
6651 return WERR_BADFID;
6653 result = winreg_get_printer_internal(p->mem_ctx,
6654 get_session_info_system(),
6655 p->msg_ctx,
6656 lp_servicename(snum),
6657 &pinfo2);
6658 if (!W_ERROR_IS_OK(result)) {
6659 return WERR_BADFID;
6662 nt_printer_publish(pinfo2,
6663 get_session_info_system(),
6664 p->msg_ctx,
6665 pinfo2,
6666 info7->action);
6668 TALLOC_FREE(pinfo2);
6669 return WERR_OK;
6670 #else
6671 return WERR_UNKNOWN_LEVEL;
6672 #endif
6675 /********************************************************************
6676 ********************************************************************/
6678 static WERROR update_printer_devmode(struct pipes_struct *p,
6679 struct policy_handle *handle,
6680 struct spoolss_DeviceMode *devmode)
6682 int snum;
6683 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6684 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6686 DEBUG(8,("update_printer_devmode\n"));
6688 if (!Printer) {
6689 return WERR_BADFID;
6692 if (!get_printer_snum(p, handle, &snum, NULL)) {
6693 return WERR_BADFID;
6696 /* Check calling user has permission to update printer description */
6697 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6698 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6699 return WERR_ACCESS_DENIED;
6702 return winreg_update_printer_internal(p->mem_ctx,
6703 get_session_info_system(),
6704 p->msg_ctx,
6705 lp_const_servicename(snum),
6706 info2_mask,
6707 NULL,
6708 devmode,
6709 NULL);
6713 /****************************************************************
6714 _spoolss_SetPrinter
6715 ****************************************************************/
6717 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6718 struct spoolss_SetPrinter *r)
6720 WERROR result;
6722 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6724 if (!Printer) {
6725 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6726 OUR_HANDLE(r->in.handle)));
6727 return WERR_BADFID;
6730 /* check the level */
6731 switch (r->in.info_ctr->level) {
6732 case 0:
6733 return control_printer(r->in.handle, r->in.command, p);
6734 case 2:
6735 result = update_printer(p, r->in.handle,
6736 r->in.info_ctr,
6737 r->in.devmode_ctr->devmode);
6738 if (!W_ERROR_IS_OK(result))
6739 return result;
6740 if (r->in.secdesc_ctr->sd)
6741 result = update_printer_sec(r->in.handle, p,
6742 r->in.secdesc_ctr);
6743 return result;
6744 case 3:
6745 return update_printer_sec(r->in.handle, p,
6746 r->in.secdesc_ctr);
6747 case 7:
6748 return publish_or_unpublish_printer(p, r->in.handle,
6749 r->in.info_ctr->info.info7);
6750 case 8:
6751 return update_printer_devmode(p, r->in.handle,
6752 r->in.devmode_ctr->devmode);
6753 default:
6754 return WERR_UNKNOWN_LEVEL;
6758 /****************************************************************
6759 _spoolss_FindClosePrinterNotify
6760 ****************************************************************/
6762 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
6763 struct spoolss_FindClosePrinterNotify *r)
6765 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6767 if (!Printer) {
6768 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6769 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6770 return WERR_BADFID;
6773 if (Printer->notify.cli_chan != NULL &&
6774 Printer->notify.cli_chan->active_connections > 0) {
6775 int snum = -1;
6777 if (Printer->printer_type == SPLHND_PRINTER) {
6778 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6779 return WERR_BADFID;
6783 srv_spoolss_replycloseprinter(snum, Printer);
6786 Printer->notify.flags=0;
6787 Printer->notify.options=0;
6788 Printer->notify.localmachine[0]='\0';
6789 Printer->notify.printerlocal=0;
6790 TALLOC_FREE(Printer->notify.option);
6792 return WERR_OK;
6795 /****************************************************************
6796 _spoolss_AddJob
6797 ****************************************************************/
6799 WERROR _spoolss_AddJob(struct pipes_struct *p,
6800 struct spoolss_AddJob *r)
6802 if (!r->in.buffer && (r->in.offered != 0)) {
6803 return WERR_INVALID_PARAM;
6806 /* this is what a NT server returns for AddJob. AddJob must fail on
6807 * non-local printers */
6809 if (r->in.level != 1) {
6810 return WERR_UNKNOWN_LEVEL;
6813 return WERR_INVALID_PARAM;
6816 /****************************************************************************
6817 fill_job_info1
6818 ****************************************************************************/
6820 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6821 struct spoolss_JobInfo1 *r,
6822 const print_queue_struct *queue,
6823 int position, int snum,
6824 struct spoolss_PrinterInfo2 *pinfo2)
6826 struct tm *t;
6828 t = gmtime(&queue->time);
6830 r->job_id = queue->job;
6832 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6833 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6834 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
6835 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6836 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6837 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6838 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6839 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6840 r->data_type = talloc_strdup(mem_ctx, "RAW");
6841 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6842 r->text_status = talloc_strdup(mem_ctx, "");
6843 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6845 r->status = nt_printj_status(queue->status);
6846 r->priority = queue->priority;
6847 r->position = position;
6848 r->total_pages = queue->page_count;
6849 r->pages_printed = 0; /* ??? */
6851 init_systemtime(&r->submitted, t);
6853 return WERR_OK;
6856 /****************************************************************************
6857 fill_job_info2
6858 ****************************************************************************/
6860 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6861 struct spoolss_JobInfo2 *r,
6862 const print_queue_struct *queue,
6863 int position, int snum,
6864 struct spoolss_PrinterInfo2 *pinfo2,
6865 struct spoolss_DeviceMode *devmode)
6867 struct tm *t;
6869 t = gmtime(&queue->time);
6871 r->job_id = queue->job;
6873 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6874 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6875 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
6876 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6877 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6878 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6879 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6880 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6881 r->notify_name = talloc_strdup(mem_ctx, queue->fs_user);
6882 W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6883 r->data_type = talloc_strdup(mem_ctx, "RAW");
6884 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6885 r->print_processor = talloc_strdup(mem_ctx, "winprint");
6886 W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6887 r->parameters = talloc_strdup(mem_ctx, "");
6888 W_ERROR_HAVE_NO_MEMORY(r->parameters);
6889 r->driver_name = talloc_strdup(mem_ctx, pinfo2->drivername);
6890 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6892 r->devmode = devmode;
6894 r->text_status = talloc_strdup(mem_ctx, "");
6895 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6897 r->secdesc = NULL;
6899 r->status = nt_printj_status(queue->status);
6900 r->priority = queue->priority;
6901 r->position = position;
6902 r->start_time = 0;
6903 r->until_time = 0;
6904 r->total_pages = queue->page_count;
6905 r->size = queue->size;
6906 init_systemtime(&r->submitted, t);
6907 r->time = 0;
6908 r->pages_printed = 0; /* ??? */
6910 return WERR_OK;
6913 /****************************************************************************
6914 fill_job_info3
6915 ****************************************************************************/
6917 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6918 struct spoolss_JobInfo3 *r,
6919 const print_queue_struct *queue,
6920 const print_queue_struct *next_queue,
6921 int position, int snum,
6922 struct spoolss_PrinterInfo2 *pinfo2)
6924 r->job_id = queue->job;
6925 r->next_job_id = 0;
6926 if (next_queue) {
6927 r->next_job_id = next_queue->job;
6929 r->reserved = 0;
6931 return WERR_OK;
6934 /****************************************************************************
6935 Enumjobs at level 1.
6936 ****************************************************************************/
6938 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6939 const print_queue_struct *queue,
6940 uint32_t num_queues, int snum,
6941 struct spoolss_PrinterInfo2 *pinfo2,
6942 union spoolss_JobInfo **info_p,
6943 uint32_t *count)
6945 union spoolss_JobInfo *info;
6946 int i;
6947 WERROR result = WERR_OK;
6949 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6950 W_ERROR_HAVE_NO_MEMORY(info);
6952 *count = num_queues;
6954 for (i=0; i<*count; i++) {
6955 result = fill_job_info1(info,
6956 &info[i].info1,
6957 &queue[i],
6959 snum,
6960 pinfo2);
6961 if (!W_ERROR_IS_OK(result)) {
6962 goto out;
6966 out:
6967 if (!W_ERROR_IS_OK(result)) {
6968 TALLOC_FREE(info);
6969 *count = 0;
6970 return result;
6973 *info_p = info;
6975 return WERR_OK;
6978 /****************************************************************************
6979 Enumjobs at level 2.
6980 ****************************************************************************/
6982 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6983 const print_queue_struct *queue,
6984 uint32_t num_queues, int snum,
6985 struct spoolss_PrinterInfo2 *pinfo2,
6986 union spoolss_JobInfo **info_p,
6987 uint32_t *count)
6989 union spoolss_JobInfo *info;
6990 int i;
6991 WERROR result = WERR_OK;
6993 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6994 W_ERROR_HAVE_NO_MEMORY(info);
6996 *count = num_queues;
6998 for (i=0; i<*count; i++) {
6999 struct spoolss_DeviceMode *devmode;
7001 result = spoolss_create_default_devmode(info,
7002 pinfo2->printername,
7003 &devmode);
7004 if (!W_ERROR_IS_OK(result)) {
7005 DEBUG(3, ("Can't proceed w/o a devmode!"));
7006 goto out;
7009 result = fill_job_info2(info,
7010 &info[i].info2,
7011 &queue[i],
7013 snum,
7014 pinfo2,
7015 devmode);
7016 if (!W_ERROR_IS_OK(result)) {
7017 goto out;
7021 out:
7022 if (!W_ERROR_IS_OK(result)) {
7023 TALLOC_FREE(info);
7024 *count = 0;
7025 return result;
7028 *info_p = info;
7030 return WERR_OK;
7033 /****************************************************************************
7034 Enumjobs at level 3.
7035 ****************************************************************************/
7037 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
7038 const print_queue_struct *queue,
7039 uint32_t num_queues, int snum,
7040 struct spoolss_PrinterInfo2 *pinfo2,
7041 union spoolss_JobInfo **info_p,
7042 uint32_t *count)
7044 union spoolss_JobInfo *info;
7045 int i;
7046 WERROR result = WERR_OK;
7048 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
7049 W_ERROR_HAVE_NO_MEMORY(info);
7051 *count = num_queues;
7053 for (i=0; i<*count; i++) {
7054 const print_queue_struct *next_queue = NULL;
7056 if (i+1 < *count) {
7057 next_queue = &queue[i+1];
7060 result = fill_job_info3(info,
7061 &info[i].info3,
7062 &queue[i],
7063 next_queue,
7065 snum,
7066 pinfo2);
7067 if (!W_ERROR_IS_OK(result)) {
7068 goto out;
7072 out:
7073 if (!W_ERROR_IS_OK(result)) {
7074 TALLOC_FREE(info);
7075 *count = 0;
7076 return result;
7079 *info_p = info;
7081 return WERR_OK;
7084 /****************************************************************
7085 _spoolss_EnumJobs
7086 ****************************************************************/
7088 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7089 struct spoolss_EnumJobs *r)
7091 WERROR result;
7092 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7093 int snum;
7094 print_status_struct prt_status;
7095 print_queue_struct *queue = NULL;
7096 uint32_t count;
7098 /* that's an [in out] buffer */
7100 if (!r->in.buffer && (r->in.offered != 0)) {
7101 return WERR_INVALID_PARAM;
7104 DEBUG(4,("_spoolss_EnumJobs\n"));
7106 *r->out.needed = 0;
7107 *r->out.count = 0;
7108 *r->out.info = NULL;
7110 /* lookup the printer snum and tdb entry */
7112 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7113 return WERR_BADFID;
7116 result = winreg_get_printer_internal(p->mem_ctx,
7117 get_session_info_system(),
7118 p->msg_ctx,
7119 lp_const_servicename(snum),
7120 &pinfo2);
7121 if (!W_ERROR_IS_OK(result)) {
7122 return result;
7125 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7126 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7127 count, prt_status.status, prt_status.message));
7129 if (count == 0) {
7130 SAFE_FREE(queue);
7131 TALLOC_FREE(pinfo2);
7132 return WERR_OK;
7135 switch (r->in.level) {
7136 case 1:
7137 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7138 pinfo2, r->out.info, r->out.count);
7139 break;
7140 case 2:
7141 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7142 pinfo2, r->out.info, r->out.count);
7143 break;
7144 case 3:
7145 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7146 pinfo2, r->out.info, r->out.count);
7147 break;
7148 default:
7149 result = WERR_UNKNOWN_LEVEL;
7150 break;
7153 SAFE_FREE(queue);
7154 TALLOC_FREE(pinfo2);
7156 if (!W_ERROR_IS_OK(result)) {
7157 return result;
7160 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7161 spoolss_EnumJobs,
7162 *r->out.info, r->in.level,
7163 *r->out.count);
7164 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7165 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7167 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7170 /****************************************************************
7171 _spoolss_ScheduleJob
7172 ****************************************************************/
7174 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7175 struct spoolss_ScheduleJob *r)
7177 return WERR_OK;
7180 /****************************************************************
7181 ****************************************************************/
7183 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7184 struct messaging_context *msg_ctx,
7185 const char *printer_name,
7186 uint32_t job_id,
7187 struct spoolss_SetJobInfo1 *r)
7189 char *old_doc_name;
7191 if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7192 return WERR_BADFID;
7195 if (strequal(old_doc_name, r->document_name)) {
7196 return WERR_OK;
7199 if (!print_job_set_name(server_event_context(), msg_ctx,
7200 printer_name, job_id, r->document_name)) {
7201 return WERR_BADFID;
7204 return WERR_OK;
7207 /****************************************************************
7208 _spoolss_SetJob
7209 ****************************************************************/
7211 WERROR _spoolss_SetJob(struct pipes_struct *p,
7212 struct spoolss_SetJob *r)
7214 const struct auth_serversupplied_info *session_info = p->session_info;
7215 int snum;
7216 WERROR errcode = WERR_BADFUNC;
7218 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7219 return WERR_BADFID;
7222 if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7223 return WERR_INVALID_PRINTER_NAME;
7226 switch (r->in.command) {
7227 case SPOOLSS_JOB_CONTROL_CANCEL:
7228 case SPOOLSS_JOB_CONTROL_DELETE:
7229 errcode = print_job_delete(session_info, p->msg_ctx,
7230 snum, r->in.job_id);
7231 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7232 errcode = WERR_OK;
7234 break;
7235 case SPOOLSS_JOB_CONTROL_PAUSE:
7236 if (print_job_pause(session_info, p->msg_ctx,
7237 snum, r->in.job_id, &errcode)) {
7238 errcode = WERR_OK;
7240 break;
7241 case SPOOLSS_JOB_CONTROL_RESTART:
7242 case SPOOLSS_JOB_CONTROL_RESUME:
7243 if (print_job_resume(session_info, p->msg_ctx,
7244 snum, r->in.job_id, &errcode)) {
7245 errcode = WERR_OK;
7247 break;
7248 case 0:
7249 errcode = WERR_OK;
7250 break;
7251 default:
7252 return WERR_UNKNOWN_LEVEL;
7255 if (!W_ERROR_IS_OK(errcode)) {
7256 return errcode;
7259 if (r->in.ctr == NULL) {
7260 return errcode;
7263 switch (r->in.ctr->level) {
7264 case 1:
7265 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7266 lp_const_servicename(snum),
7267 r->in.job_id,
7268 r->in.ctr->info.info1);
7269 break;
7270 case 2:
7271 case 3:
7272 case 4:
7273 default:
7274 return WERR_UNKNOWN_LEVEL;
7277 return errcode;
7280 /****************************************************************************
7281 Enumerates all printer drivers by level and architecture.
7282 ****************************************************************************/
7284 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7285 const struct auth_serversupplied_info *session_info,
7286 struct messaging_context *msg_ctx,
7287 const char *servername,
7288 const char *architecture,
7289 uint32_t level,
7290 union spoolss_DriverInfo **info_p,
7291 uint32_t *count_p)
7293 int i;
7294 uint32_t version;
7295 struct spoolss_DriverInfo8 *driver;
7296 union spoolss_DriverInfo *info = NULL;
7297 uint32_t count = 0;
7298 WERROR result = WERR_OK;
7299 uint32_t num_drivers;
7300 const char **drivers;
7301 struct dcerpc_binding_handle *b;
7303 *count_p = 0;
7304 *info_p = NULL;
7306 result = winreg_printer_binding_handle(mem_ctx,
7307 session_info,
7308 msg_ctx,
7309 &b);
7310 if (!W_ERROR_IS_OK(result)) {
7311 goto out;
7314 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7315 result = winreg_get_driver_list(mem_ctx, b,
7316 architecture, version,
7317 &num_drivers, &drivers);
7318 if (!W_ERROR_IS_OK(result)) {
7319 goto out;
7321 DEBUG(4, ("we have:[%d] drivers in environment"
7322 " [%s] and version [%d]\n",
7323 num_drivers, architecture, version));
7325 if (num_drivers != 0) {
7326 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
7327 union spoolss_DriverInfo,
7328 count + num_drivers);
7329 if (!info) {
7330 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7331 "failed to enlarge driver info buffer!\n"));
7332 result = WERR_NOMEM;
7333 goto out;
7337 for (i = 0; i < num_drivers; i++) {
7338 DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7340 result = winreg_get_driver(mem_ctx, b,
7341 architecture, drivers[i],
7342 version, &driver);
7343 if (!W_ERROR_IS_OK(result)) {
7344 goto out;
7347 switch (level) {
7348 case 1:
7349 result = fill_printer_driver_info1(info, &info[count+i].info1,
7350 driver, servername);
7351 break;
7352 case 2:
7353 result = fill_printer_driver_info2(info, &info[count+i].info2,
7354 driver, servername);
7355 break;
7356 case 3:
7357 result = fill_printer_driver_info3(info, &info[count+i].info3,
7358 driver, servername);
7359 break;
7360 case 4:
7361 result = fill_printer_driver_info4(info, &info[count+i].info4,
7362 driver, servername);
7363 break;
7364 case 5:
7365 result = fill_printer_driver_info5(info, &info[count+i].info5,
7366 driver, servername);
7367 break;
7368 case 6:
7369 result = fill_printer_driver_info6(info, &info[count+i].info6,
7370 driver, servername);
7371 break;
7372 case 8:
7373 result = fill_printer_driver_info8(info, &info[count+i].info8,
7374 driver, servername);
7375 break;
7376 default:
7377 result = WERR_UNKNOWN_LEVEL;
7378 break;
7381 TALLOC_FREE(driver);
7383 if (!W_ERROR_IS_OK(result)) {
7384 goto out;
7388 count += num_drivers;
7389 TALLOC_FREE(drivers);
7392 out:
7393 TALLOC_FREE(drivers);
7395 if (!W_ERROR_IS_OK(result)) {
7396 TALLOC_FREE(info);
7397 return result;
7400 *info_p = info;
7401 *count_p = count;
7403 return WERR_OK;
7406 /****************************************************************************
7407 Enumerates all printer drivers by level.
7408 ****************************************************************************/
7410 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7411 const struct auth_serversupplied_info *session_info,
7412 struct messaging_context *msg_ctx,
7413 const char *servername,
7414 const char *architecture,
7415 uint32_t level,
7416 union spoolss_DriverInfo **info_p,
7417 uint32_t *count_p)
7419 uint32_t a,i;
7420 WERROR result = WERR_OK;
7422 if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7424 for (a=0; archi_table[a].long_archi != NULL; a++) {
7426 union spoolss_DriverInfo *info = NULL;
7427 uint32_t count = 0;
7429 result = enumprinterdrivers_level_by_architecture(mem_ctx,
7430 session_info,
7431 msg_ctx,
7432 servername,
7433 archi_table[a].long_archi,
7434 level,
7435 &info,
7436 &count);
7437 if (!W_ERROR_IS_OK(result)) {
7438 continue;
7441 for (i=0; i < count; i++) {
7442 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7443 info[i], info_p, count_p);
7447 return result;
7450 return enumprinterdrivers_level_by_architecture(mem_ctx,
7451 session_info,
7452 msg_ctx,
7453 servername,
7454 architecture,
7455 level,
7456 info_p,
7457 count_p);
7460 /****************************************************************
7461 _spoolss_EnumPrinterDrivers
7462 ****************************************************************/
7464 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7465 struct spoolss_EnumPrinterDrivers *r)
7467 const char *cservername;
7468 WERROR result;
7470 /* that's an [in out] buffer */
7472 if (!r->in.buffer && (r->in.offered != 0)) {
7473 return WERR_INVALID_PARAM;
7476 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7478 *r->out.needed = 0;
7479 *r->out.count = 0;
7480 *r->out.info = NULL;
7482 cservername = canon_servername(r->in.server);
7484 if (!is_myname_or_ipaddr(cservername)) {
7485 return WERR_UNKNOWN_PRINTER_DRIVER;
7488 result = enumprinterdrivers_level(p->mem_ctx,
7489 get_session_info_system(),
7490 p->msg_ctx,
7491 cservername,
7492 r->in.environment,
7493 r->in.level,
7494 r->out.info,
7495 r->out.count);
7496 if (!W_ERROR_IS_OK(result)) {
7497 return result;
7500 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7501 spoolss_EnumPrinterDrivers,
7502 *r->out.info, r->in.level,
7503 *r->out.count);
7504 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7505 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7507 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7510 /****************************************************************
7511 _spoolss_EnumForms
7512 ****************************************************************/
7514 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7515 struct spoolss_EnumForms *r)
7517 WERROR result;
7519 *r->out.count = 0;
7520 *r->out.needed = 0;
7521 *r->out.info = NULL;
7523 /* that's an [in out] buffer */
7525 if (!r->in.buffer && (r->in.offered != 0) ) {
7526 return WERR_INVALID_PARAM;
7529 DEBUG(4,("_spoolss_EnumForms\n"));
7530 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7531 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7533 switch (r->in.level) {
7534 case 1:
7535 result = winreg_printer_enumforms1_internal(p->mem_ctx,
7536 get_session_info_system(),
7537 p->msg_ctx,
7538 r->out.count,
7539 r->out.info);
7540 break;
7541 default:
7542 result = WERR_UNKNOWN_LEVEL;
7543 break;
7546 if (!W_ERROR_IS_OK(result)) {
7547 return result;
7550 if (*r->out.count == 0) {
7551 return WERR_NO_MORE_ITEMS;
7554 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7555 spoolss_EnumForms,
7556 *r->out.info, r->in.level,
7557 *r->out.count);
7558 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7559 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7561 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7564 /****************************************************************
7565 _spoolss_GetForm
7566 ****************************************************************/
7568 WERROR _spoolss_GetForm(struct pipes_struct *p,
7569 struct spoolss_GetForm *r)
7571 WERROR result;
7573 /* that's an [in out] buffer */
7575 if (!r->in.buffer && (r->in.offered != 0)) {
7576 return WERR_INVALID_PARAM;
7579 DEBUG(4,("_spoolss_GetForm\n"));
7580 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7581 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7583 switch (r->in.level) {
7584 case 1:
7585 result = winreg_printer_getform1_internal(p->mem_ctx,
7586 get_session_info_system(),
7587 p->msg_ctx,
7588 r->in.form_name,
7589 &r->out.info->info1);
7590 break;
7591 default:
7592 result = WERR_UNKNOWN_LEVEL;
7593 break;
7596 if (!W_ERROR_IS_OK(result)) {
7597 TALLOC_FREE(r->out.info);
7598 return result;
7601 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
7602 r->out.info, r->in.level);
7603 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7605 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7608 /****************************************************************************
7609 ****************************************************************************/
7611 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7612 struct spoolss_PortInfo1 *r,
7613 const char *name)
7615 r->port_name = talloc_strdup(mem_ctx, name);
7616 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7618 return WERR_OK;
7621 /****************************************************************************
7622 TODO: This probably needs distinguish between TCP/IP and Local ports
7623 somehow.
7624 ****************************************************************************/
7626 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7627 struct spoolss_PortInfo2 *r,
7628 const char *name)
7630 r->port_name = talloc_strdup(mem_ctx, name);
7631 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7633 r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7634 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7636 r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7637 W_ERROR_HAVE_NO_MEMORY(r->description);
7639 r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7640 r->reserved = 0;
7642 return WERR_OK;
7646 /****************************************************************************
7647 wrapper around the enumer ports command
7648 ****************************************************************************/
7650 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7652 char *cmd = lp_enumports_cmd();
7653 char **qlines = NULL;
7654 char *command = NULL;
7655 int numlines;
7656 int ret;
7657 int fd;
7659 *count = 0;
7660 *lines = NULL;
7662 /* if no hook then just fill in the default port */
7664 if ( !*cmd ) {
7665 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7666 return WERR_NOMEM;
7668 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7669 TALLOC_FREE(qlines);
7670 return WERR_NOMEM;
7672 qlines[1] = NULL;
7673 numlines = 1;
7675 else {
7676 /* we have a valid enumport command */
7678 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7679 if (!command) {
7680 return WERR_NOMEM;
7683 DEBUG(10,("Running [%s]\n", command));
7684 ret = smbrun(command, &fd);
7685 DEBUG(10,("Returned [%d]\n", ret));
7686 TALLOC_FREE(command);
7687 if (ret != 0) {
7688 if (fd != -1) {
7689 close(fd);
7691 return WERR_ACCESS_DENIED;
7694 numlines = 0;
7695 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7696 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7697 close(fd);
7700 *count = numlines;
7701 *lines = qlines;
7703 return WERR_OK;
7706 /****************************************************************************
7707 enumports level 1.
7708 ****************************************************************************/
7710 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7711 union spoolss_PortInfo **info_p,
7712 uint32_t *count)
7714 union spoolss_PortInfo *info = NULL;
7715 int i=0;
7716 WERROR result = WERR_OK;
7717 char **qlines = NULL;
7718 int numlines = 0;
7720 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7721 if (!W_ERROR_IS_OK(result)) {
7722 goto out;
7725 if (numlines) {
7726 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7727 if (!info) {
7728 DEBUG(10,("Returning WERR_NOMEM\n"));
7729 result = WERR_NOMEM;
7730 goto out;
7733 for (i=0; i<numlines; i++) {
7734 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7735 result = fill_port_1(info, &info[i].info1, qlines[i]);
7736 if (!W_ERROR_IS_OK(result)) {
7737 goto out;
7741 TALLOC_FREE(qlines);
7743 out:
7744 if (!W_ERROR_IS_OK(result)) {
7745 TALLOC_FREE(info);
7746 TALLOC_FREE(qlines);
7747 *count = 0;
7748 *info_p = NULL;
7749 return result;
7752 *info_p = info;
7753 *count = numlines;
7755 return WERR_OK;
7758 /****************************************************************************
7759 enumports level 2.
7760 ****************************************************************************/
7762 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7763 union spoolss_PortInfo **info_p,
7764 uint32_t *count)
7766 union spoolss_PortInfo *info = NULL;
7767 int i=0;
7768 WERROR result = WERR_OK;
7769 char **qlines = NULL;
7770 int numlines = 0;
7772 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7773 if (!W_ERROR_IS_OK(result)) {
7774 goto out;
7777 if (numlines) {
7778 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7779 if (!info) {
7780 DEBUG(10,("Returning WERR_NOMEM\n"));
7781 result = WERR_NOMEM;
7782 goto out;
7785 for (i=0; i<numlines; i++) {
7786 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7787 result = fill_port_2(info, &info[i].info2, qlines[i]);
7788 if (!W_ERROR_IS_OK(result)) {
7789 goto out;
7793 TALLOC_FREE(qlines);
7795 out:
7796 if (!W_ERROR_IS_OK(result)) {
7797 TALLOC_FREE(info);
7798 TALLOC_FREE(qlines);
7799 *count = 0;
7800 *info_p = NULL;
7801 return result;
7804 *info_p = info;
7805 *count = numlines;
7807 return WERR_OK;
7810 /****************************************************************
7811 _spoolss_EnumPorts
7812 ****************************************************************/
7814 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
7815 struct spoolss_EnumPorts *r)
7817 WERROR result;
7819 /* that's an [in out] buffer */
7821 if (!r->in.buffer && (r->in.offered != 0)) {
7822 return WERR_INVALID_PARAM;
7825 DEBUG(4,("_spoolss_EnumPorts\n"));
7827 *r->out.count = 0;
7828 *r->out.needed = 0;
7829 *r->out.info = NULL;
7831 switch (r->in.level) {
7832 case 1:
7833 result = enumports_level_1(p->mem_ctx, r->out.info,
7834 r->out.count);
7835 break;
7836 case 2:
7837 result = enumports_level_2(p->mem_ctx, r->out.info,
7838 r->out.count);
7839 break;
7840 default:
7841 return WERR_UNKNOWN_LEVEL;
7844 if (!W_ERROR_IS_OK(result)) {
7845 return result;
7848 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7849 spoolss_EnumPorts,
7850 *r->out.info, r->in.level,
7851 *r->out.count);
7852 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7853 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7855 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7858 /****************************************************************************
7859 ****************************************************************************/
7861 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
7862 const char *server,
7863 struct spoolss_SetPrinterInfoCtr *info_ctr,
7864 struct spoolss_DeviceMode *devmode,
7865 struct security_descriptor *secdesc,
7866 struct spoolss_UserLevelCtr *user_ctr,
7867 struct policy_handle *handle)
7869 struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
7870 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
7871 int snum;
7872 WERROR err = WERR_OK;
7874 /* samba does not have a concept of local, non-shared printers yet, so
7875 * make sure we always setup sharename - gd */
7876 if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
7877 (info2->printername != NULL && info2->printername[0] != '\0')) {
7878 DEBUG(5, ("spoolss_addprinterex_level_2: "
7879 "no sharename has been set, setting printername %s as sharename\n",
7880 info2->printername));
7881 info2->sharename = info2->printername;
7884 /* check to see if the printer already exists */
7885 if ((snum = print_queue_snum(info2->sharename)) != -1) {
7886 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7887 info2->sharename));
7888 return WERR_PRINTER_ALREADY_EXISTS;
7891 if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7892 if ((snum = print_queue_snum(info2->printername)) != -1) {
7893 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7894 info2->printername));
7895 return WERR_PRINTER_ALREADY_EXISTS;
7899 /* validate printer info struct */
7900 if (!info2->printername || strlen(info2->printername) == 0) {
7901 return WERR_INVALID_PRINTER_NAME;
7903 if (!info2->portname || strlen(info2->portname) == 0) {
7904 return WERR_UNKNOWN_PORT;
7906 if (!info2->drivername || strlen(info2->drivername) == 0) {
7907 return WERR_UNKNOWN_PRINTER_DRIVER;
7909 if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
7910 return WERR_UNKNOWN_PRINTPROCESSOR;
7913 /* FIXME!!! smbd should check to see if the driver is installed before
7914 trying to add a printer like this --jerry */
7916 if (*lp_addprinter_cmd() ) {
7917 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
7918 info2, p->client_id->addr,
7919 p->msg_ctx) ) {
7920 return WERR_ACCESS_DENIED;
7922 } else {
7923 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
7924 "smb.conf parameter \"addprinter command\" is defined. This "
7925 "parameter must exist for this call to succeed\n",
7926 info2->sharename ));
7929 if ((snum = print_queue_snum(info2->sharename)) == -1) {
7930 return WERR_ACCESS_DENIED;
7933 /* you must be a printer admin to add a new printer */
7934 if (!print_access_check(p->session_info,
7935 p->msg_ctx,
7936 snum,
7937 PRINTER_ACCESS_ADMINISTER)) {
7938 return WERR_ACCESS_DENIED;
7942 * Do sanity check on the requested changes for Samba.
7945 if (!check_printer_ok(p->mem_ctx, info2, snum)) {
7946 return WERR_INVALID_PARAM;
7949 if (devmode == NULL) {
7950 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
7953 update_dsspooler(p->mem_ctx,
7954 get_session_info_system(),
7955 p->msg_ctx,
7957 info2,
7958 NULL);
7960 err = winreg_update_printer_internal(p->mem_ctx,
7961 get_session_info_system(),
7962 p->msg_ctx,
7963 info2->sharename,
7964 info2_mask,
7965 info2,
7966 devmode,
7967 secdesc);
7968 if (!W_ERROR_IS_OK(err)) {
7969 return err;
7972 err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
7973 if (!W_ERROR_IS_OK(err)) {
7974 /* Handle open failed - remove addition. */
7975 ZERO_STRUCTP(handle);
7976 return err;
7979 return WERR_OK;
7982 /****************************************************************
7983 _spoolss_AddPrinterEx
7984 ****************************************************************/
7986 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
7987 struct spoolss_AddPrinterEx *r)
7989 switch (r->in.info_ctr->level) {
7990 case 1:
7991 /* we don't handle yet */
7992 /* but I know what to do ... */
7993 return WERR_UNKNOWN_LEVEL;
7994 case 2:
7995 return spoolss_addprinterex_level_2(p, r->in.server,
7996 r->in.info_ctr,
7997 r->in.devmode_ctr->devmode,
7998 r->in.secdesc_ctr->sd,
7999 r->in.userlevel_ctr,
8000 r->out.handle);
8001 default:
8002 return WERR_UNKNOWN_LEVEL;
8006 /****************************************************************
8007 _spoolss_AddPrinter
8008 ****************************************************************/
8010 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
8011 struct spoolss_AddPrinter *r)
8013 struct spoolss_AddPrinterEx a;
8014 struct spoolss_UserLevelCtr userlevel_ctr;
8016 ZERO_STRUCT(userlevel_ctr);
8018 userlevel_ctr.level = 1;
8020 a.in.server = r->in.server;
8021 a.in.info_ctr = r->in.info_ctr;
8022 a.in.devmode_ctr = r->in.devmode_ctr;
8023 a.in.secdesc_ctr = r->in.secdesc_ctr;
8024 a.in.userlevel_ctr = &userlevel_ctr;
8025 a.out.handle = r->out.handle;
8027 return _spoolss_AddPrinterEx(p, &a);
8030 /****************************************************************
8031 _spoolss_AddPrinterDriverEx
8032 ****************************************************************/
8034 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
8035 struct spoolss_AddPrinterDriverEx *r)
8037 WERROR err = WERR_OK;
8038 const char *driver_name = NULL;
8039 uint32_t version;
8040 const char *fn;
8042 switch (p->opnum) {
8043 case NDR_SPOOLSS_ADDPRINTERDRIVER:
8044 fn = "_spoolss_AddPrinterDriver";
8045 break;
8046 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
8047 fn = "_spoolss_AddPrinterDriverEx";
8048 break;
8049 default:
8050 return WERR_INVALID_PARAM;
8054 * we only support the semantics of AddPrinterDriver()
8055 * i.e. only copy files that are newer than existing ones
8058 if (r->in.flags == 0) {
8059 return WERR_INVALID_PARAM;
8062 if (r->in.flags != APD_COPY_NEW_FILES) {
8063 return WERR_ACCESS_DENIED;
8066 /* FIXME */
8067 if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
8068 /* Clever hack from Martin Zielinski <mz@seh.de>
8069 * to allow downgrade from level 8 (Vista).
8071 DEBUG(0,("%s: level %d not yet implemented\n", fn,
8072 r->in.info_ctr->level));
8073 return WERR_UNKNOWN_LEVEL;
8076 DEBUG(5,("Cleaning driver's information\n"));
8077 err = clean_up_driver_struct(p->mem_ctx, p->session_info, r->in.info_ctr);
8078 if (!W_ERROR_IS_OK(err))
8079 goto done;
8081 DEBUG(5,("Moving driver to final destination\n"));
8082 err = move_driver_to_download_area(p->session_info, r->in.info_ctr);
8083 if (!W_ERROR_IS_OK(err)) {
8084 goto done;
8087 err = winreg_add_driver_internal(p->mem_ctx,
8088 get_session_info_system(),
8089 p->msg_ctx,
8090 r->in.info_ctr,
8091 &driver_name,
8092 &version);
8093 if (!W_ERROR_IS_OK(err)) {
8094 goto done;
8098 * I think this is where he DrvUpgradePrinter() hook would be
8099 * be called in a driver's interface DLL on a Windows NT 4.0/2k
8100 * server. Right now, we just need to send ourselves a message
8101 * to update each printer bound to this driver. --jerry
8104 if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8105 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8106 fn, driver_name));
8109 done:
8110 return err;
8113 /****************************************************************
8114 _spoolss_AddPrinterDriver
8115 ****************************************************************/
8117 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8118 struct spoolss_AddPrinterDriver *r)
8120 struct spoolss_AddPrinterDriverEx a;
8122 switch (r->in.info_ctr->level) {
8123 case 2:
8124 case 3:
8125 case 4:
8126 case 5:
8127 break;
8128 default:
8129 return WERR_UNKNOWN_LEVEL;
8132 a.in.servername = r->in.servername;
8133 a.in.info_ctr = r->in.info_ctr;
8134 a.in.flags = APD_COPY_NEW_FILES;
8136 return _spoolss_AddPrinterDriverEx(p, &a);
8139 /****************************************************************************
8140 ****************************************************************************/
8142 struct _spoolss_paths {
8143 int type;
8144 const char *share;
8145 const char *dir;
8148 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8150 static const struct _spoolss_paths spoolss_paths[]= {
8151 { SPOOLSS_DRIVER_PATH, "print$", "DRIVERS" },
8152 { SPOOLSS_PRTPROCS_PATH, "prnproc$", "PRTPROCS" }
8155 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8156 const char *servername,
8157 const char *environment,
8158 int component,
8159 char **path)
8161 const char *pservername = NULL;
8162 const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
8163 const char *short_archi;
8165 *path = NULL;
8167 /* environment may be empty */
8168 if (environment && strlen(environment)) {
8169 long_archi = environment;
8172 /* servername may be empty */
8173 if (servername && strlen(servername)) {
8174 pservername = canon_servername(servername);
8176 if (!is_myname_or_ipaddr(pservername)) {
8177 return WERR_INVALID_PARAM;
8181 if (!(short_archi = get_short_archi(long_archi))) {
8182 return WERR_INVALID_ENVIRONMENT;
8185 switch (component) {
8186 case SPOOLSS_PRTPROCS_PATH:
8187 case SPOOLSS_DRIVER_PATH:
8188 if (pservername) {
8189 *path = talloc_asprintf(mem_ctx,
8190 "\\\\%s\\%s\\%s",
8191 pservername,
8192 spoolss_paths[component].share,
8193 short_archi);
8194 } else {
8195 *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8196 SPOOLSS_DEFAULT_SERVER_PATH,
8197 spoolss_paths[component].dir,
8198 short_archi);
8200 break;
8201 default:
8202 return WERR_INVALID_PARAM;
8205 if (!*path) {
8206 return WERR_NOMEM;
8209 return WERR_OK;
8212 /****************************************************************************
8213 ****************************************************************************/
8215 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8216 const char *servername,
8217 const char *environment,
8218 struct spoolss_DriverDirectoryInfo1 *r)
8220 WERROR werr;
8221 char *path = NULL;
8223 werr = compose_spoolss_server_path(mem_ctx,
8224 servername,
8225 environment,
8226 SPOOLSS_DRIVER_PATH,
8227 &path);
8228 if (!W_ERROR_IS_OK(werr)) {
8229 return werr;
8232 DEBUG(4,("printer driver directory: [%s]\n", path));
8234 r->directory_name = path;
8236 return WERR_OK;
8239 /****************************************************************
8240 _spoolss_GetPrinterDriverDirectory
8241 ****************************************************************/
8243 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8244 struct spoolss_GetPrinterDriverDirectory *r)
8246 WERROR werror;
8248 /* that's an [in out] buffer */
8250 if (!r->in.buffer && (r->in.offered != 0)) {
8251 return WERR_INVALID_PARAM;
8254 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8255 r->in.level));
8257 *r->out.needed = 0;
8259 /* r->in.level is ignored */
8261 werror = getprinterdriverdir_level_1(p->mem_ctx,
8262 r->in.server,
8263 r->in.environment,
8264 &r->out.info->info1);
8265 if (!W_ERROR_IS_OK(werror)) {
8266 TALLOC_FREE(r->out.info);
8267 return werror;
8270 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8271 r->out.info, r->in.level);
8272 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8274 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8277 /****************************************************************
8278 _spoolss_EnumPrinterData
8279 ****************************************************************/
8281 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8282 struct spoolss_EnumPrinterData *r)
8284 WERROR result;
8285 struct spoolss_EnumPrinterDataEx r2;
8286 uint32_t count;
8287 struct spoolss_PrinterEnumValues *info, *val = NULL;
8288 uint32_t needed;
8290 r2.in.handle = r->in.handle;
8291 r2.in.key_name = "PrinterDriverData";
8292 r2.in.offered = 0;
8293 r2.out.count = &count;
8294 r2.out.info = &info;
8295 r2.out.needed = &needed;
8297 result = _spoolss_EnumPrinterDataEx(p, &r2);
8298 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8299 r2.in.offered = needed;
8300 result = _spoolss_EnumPrinterDataEx(p, &r2);
8302 if (!W_ERROR_IS_OK(result)) {
8303 return result;
8307 * The NT machine wants to know the biggest size of value and data
8309 * cf: MSDN EnumPrinterData remark section
8312 if (!r->in.value_offered && !r->in.data_offered) {
8313 uint32_t biggest_valuesize = 0;
8314 uint32_t biggest_datasize = 0;
8315 int i, name_length;
8317 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8319 for (i=0; i<count; i++) {
8321 name_length = strlen(info[i].value_name);
8322 if (strlen(info[i].value_name) > biggest_valuesize) {
8323 biggest_valuesize = name_length;
8326 if (info[i].data_length > biggest_datasize) {
8327 biggest_datasize = info[i].data_length;
8330 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8331 biggest_datasize));
8334 /* the value is an UNICODE string but real_value_size is the length
8335 in bytes including the trailing 0 */
8337 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8338 *r->out.data_needed = biggest_datasize;
8340 DEBUG(6,("final values: [%d], [%d]\n",
8341 *r->out.value_needed, *r->out.data_needed));
8343 return WERR_OK;
8346 if (r->in.enum_index < count) {
8347 val = &info[r->in.enum_index];
8350 if (val == NULL) {
8351 /* out_value should default to "" or else NT4 has
8352 problems unmarshalling the response */
8354 if (r->in.value_offered) {
8355 *r->out.value_needed = 1;
8356 r->out.value_name = talloc_strdup(r, "");
8357 if (!r->out.value_name) {
8358 return WERR_NOMEM;
8360 } else {
8361 r->out.value_name = NULL;
8362 *r->out.value_needed = 0;
8365 /* the data is counted in bytes */
8367 *r->out.data_needed = r->in.data_offered;
8369 result = WERR_NO_MORE_ITEMS;
8370 } else {
8372 * the value is:
8373 * - counted in bytes in the request
8374 * - counted in UNICODE chars in the max reply
8375 * - counted in bytes in the real size
8377 * take a pause *before* coding not *during* coding
8380 /* name */
8381 if (r->in.value_offered) {
8382 r->out.value_name = talloc_strdup(r, val->value_name);
8383 if (!r->out.value_name) {
8384 return WERR_NOMEM;
8386 *r->out.value_needed = val->value_name_len;
8387 } else {
8388 r->out.value_name = NULL;
8389 *r->out.value_needed = 0;
8392 /* type */
8394 *r->out.type = val->type;
8396 /* data - counted in bytes */
8399 * See the section "Dynamically Typed Query Parameters"
8400 * in MS-RPRN.
8403 if (r->out.data && val->data && val->data->data &&
8404 val->data_length && r->in.data_offered) {
8405 memcpy(r->out.data, val->data->data,
8406 MIN(val->data_length,r->in.data_offered));
8409 *r->out.data_needed = val->data_length;
8411 result = WERR_OK;
8414 return result;
8417 /****************************************************************
8418 _spoolss_SetPrinterData
8419 ****************************************************************/
8421 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8422 struct spoolss_SetPrinterData *r)
8424 struct spoolss_SetPrinterDataEx r2;
8426 r2.in.handle = r->in.handle;
8427 r2.in.key_name = "PrinterDriverData";
8428 r2.in.value_name = r->in.value_name;
8429 r2.in.type = r->in.type;
8430 r2.in.data = r->in.data;
8431 r2.in.offered = r->in.offered;
8433 return _spoolss_SetPrinterDataEx(p, &r2);
8436 /****************************************************************
8437 _spoolss_ResetPrinter
8438 ****************************************************************/
8440 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8441 struct spoolss_ResetPrinter *r)
8443 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8444 int snum;
8446 DEBUG(5,("_spoolss_ResetPrinter\n"));
8449 * All we do is to check to see if the handle and queue is valid.
8450 * This call really doesn't mean anything to us because we only
8451 * support RAW printing. --jerry
8454 if (!Printer) {
8455 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8456 OUR_HANDLE(r->in.handle)));
8457 return WERR_BADFID;
8460 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8461 return WERR_BADFID;
8464 /* blindly return success */
8465 return WERR_OK;
8468 /****************************************************************
8469 _spoolss_DeletePrinterData
8470 ****************************************************************/
8472 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8473 struct spoolss_DeletePrinterData *r)
8475 struct spoolss_DeletePrinterDataEx r2;
8477 r2.in.handle = r->in.handle;
8478 r2.in.key_name = "PrinterDriverData";
8479 r2.in.value_name = r->in.value_name;
8481 return _spoolss_DeletePrinterDataEx(p, &r2);
8484 /****************************************************************
8485 _spoolss_AddForm
8486 ****************************************************************/
8488 WERROR _spoolss_AddForm(struct pipes_struct *p,
8489 struct spoolss_AddForm *r)
8491 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8492 int snum = -1;
8493 WERROR status = WERR_OK;
8494 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8495 struct dcerpc_binding_handle *b;
8497 DEBUG(5,("_spoolss_AddForm\n"));
8499 if (!Printer) {
8500 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8501 OUR_HANDLE(r->in.handle)));
8502 return WERR_BADFID;
8505 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8506 and not a printer admin, then fail */
8508 if ((p->session_info->utok.uid != sec_initial_uid()) &&
8509 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8510 !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8511 p->session_info->info3->base.domain.string,
8512 NULL,
8513 p->session_info->security_token,
8514 lp_printer_admin(snum))) {
8515 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8516 return WERR_ACCESS_DENIED;
8519 switch (form->flags) {
8520 case SPOOLSS_FORM_USER:
8521 case SPOOLSS_FORM_BUILTIN:
8522 case SPOOLSS_FORM_PRINTER:
8523 break;
8524 default:
8525 return WERR_INVALID_PARAM;
8528 status = winreg_printer_binding_handle(p->mem_ctx,
8529 get_session_info_system(),
8530 p->msg_ctx,
8531 &b);
8532 if (!W_ERROR_IS_OK(status)) {
8533 return status;
8536 status = winreg_printer_addform1(p->mem_ctx, b,
8537 form);
8538 if (!W_ERROR_IS_OK(status)) {
8539 return status;
8543 * ChangeID must always be set if this is a printer
8545 if (Printer->printer_type == SPLHND_PRINTER) {
8546 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8547 return WERR_BADFID;
8550 status = winreg_printer_update_changeid(p->mem_ctx, b,
8551 lp_const_servicename(snum));
8552 if (!W_ERROR_IS_OK(status)) {
8553 return status;
8557 return status;
8560 /****************************************************************
8561 _spoolss_DeleteForm
8562 ****************************************************************/
8564 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8565 struct spoolss_DeleteForm *r)
8567 const char *form_name = r->in.form_name;
8568 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8569 int snum = -1;
8570 WERROR status = WERR_OK;
8571 struct dcerpc_binding_handle *b;
8573 DEBUG(5,("_spoolss_DeleteForm\n"));
8575 if (!Printer) {
8576 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8577 OUR_HANDLE(r->in.handle)));
8578 return WERR_BADFID;
8581 if ((p->session_info->utok.uid != sec_initial_uid()) &&
8582 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8583 !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8584 p->session_info->info3->base.domain.string,
8585 NULL,
8586 p->session_info->security_token,
8587 lp_printer_admin(snum))) {
8588 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8589 return WERR_ACCESS_DENIED;
8592 status = winreg_printer_binding_handle(p->mem_ctx,
8593 get_session_info_system(),
8594 p->msg_ctx,
8595 &b);
8596 if (!W_ERROR_IS_OK(status)) {
8597 return status;
8600 status = winreg_printer_deleteform1(p->mem_ctx, b,
8601 form_name);
8602 if (!W_ERROR_IS_OK(status)) {
8603 return status;
8607 * ChangeID must always be set if this is a printer
8609 if (Printer->printer_type == SPLHND_PRINTER) {
8610 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8611 return WERR_BADFID;
8614 status = winreg_printer_update_changeid(p->mem_ctx, b,
8615 lp_const_servicename(snum));
8616 if (!W_ERROR_IS_OK(status)) {
8617 return status;
8621 return status;
8624 /****************************************************************
8625 _spoolss_SetForm
8626 ****************************************************************/
8628 WERROR _spoolss_SetForm(struct pipes_struct *p,
8629 struct spoolss_SetForm *r)
8631 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8632 const char *form_name = r->in.form_name;
8633 int snum = -1;
8634 WERROR status = WERR_OK;
8635 struct dcerpc_binding_handle *b;
8637 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8639 DEBUG(5,("_spoolss_SetForm\n"));
8641 if (!Printer) {
8642 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8643 OUR_HANDLE(r->in.handle)));
8644 return WERR_BADFID;
8647 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8648 and not a printer admin, then fail */
8650 if ((p->session_info->utok.uid != sec_initial_uid()) &&
8651 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8652 !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8653 p->session_info->info3->base.domain.string,
8654 NULL,
8655 p->session_info->security_token,
8656 lp_printer_admin(snum))) {
8657 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8658 return WERR_ACCESS_DENIED;
8661 status = winreg_printer_binding_handle(p->mem_ctx,
8662 get_session_info_system(),
8663 p->msg_ctx,
8664 &b);
8665 if (!W_ERROR_IS_OK(status)) {
8666 return status;
8669 status = winreg_printer_setform1(p->mem_ctx, b,
8670 form_name,
8671 form);
8672 if (!W_ERROR_IS_OK(status)) {
8673 return status;
8677 * ChangeID must always be set if this is a printer
8679 if (Printer->printer_type == SPLHND_PRINTER) {
8680 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8681 return WERR_BADFID;
8684 status = winreg_printer_update_changeid(p->mem_ctx, b,
8685 lp_const_servicename(snum));
8686 if (!W_ERROR_IS_OK(status)) {
8687 return status;
8691 return status;
8694 /****************************************************************************
8695 fill_print_processor1
8696 ****************************************************************************/
8698 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8699 struct spoolss_PrintProcessorInfo1 *r,
8700 const char *print_processor_name)
8702 r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8703 W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8705 return WERR_OK;
8708 /****************************************************************************
8709 enumprintprocessors level 1.
8710 ****************************************************************************/
8712 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8713 union spoolss_PrintProcessorInfo **info_p,
8714 uint32_t *count)
8716 union spoolss_PrintProcessorInfo *info;
8717 WERROR result;
8719 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8720 W_ERROR_HAVE_NO_MEMORY(info);
8722 *count = 1;
8724 result = fill_print_processor1(info, &info[0].info1, "winprint");
8725 if (!W_ERROR_IS_OK(result)) {
8726 goto out;
8729 out:
8730 if (!W_ERROR_IS_OK(result)) {
8731 TALLOC_FREE(info);
8732 *count = 0;
8733 return result;
8736 *info_p = info;
8738 return WERR_OK;
8741 /****************************************************************
8742 _spoolss_EnumPrintProcessors
8743 ****************************************************************/
8745 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
8746 struct spoolss_EnumPrintProcessors *r)
8748 WERROR result;
8750 /* that's an [in out] buffer */
8752 if (!r->in.buffer && (r->in.offered != 0)) {
8753 return WERR_INVALID_PARAM;
8756 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8759 * Enumerate the print processors ...
8761 * Just reply with "winprint", to keep NT happy
8762 * and I can use my nice printer checker.
8765 *r->out.count = 0;
8766 *r->out.needed = 0;
8767 *r->out.info = NULL;
8769 if (!get_short_archi(r->in.environment)) {
8770 return WERR_INVALID_ENVIRONMENT;
8773 switch (r->in.level) {
8774 case 1:
8775 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8776 r->out.count);
8777 break;
8778 default:
8779 return WERR_UNKNOWN_LEVEL;
8782 if (!W_ERROR_IS_OK(result)) {
8783 return result;
8786 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8787 spoolss_EnumPrintProcessors,
8788 *r->out.info, r->in.level,
8789 *r->out.count);
8790 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8791 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8793 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8796 /****************************************************************************
8797 fill_printprocdatatype1
8798 ****************************************************************************/
8800 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8801 struct spoolss_PrintProcDataTypesInfo1 *r,
8802 const char *name_array)
8804 r->name_array = talloc_strdup(mem_ctx, name_array);
8805 W_ERROR_HAVE_NO_MEMORY(r->name_array);
8807 return WERR_OK;
8810 /****************************************************************************
8811 enumprintprocdatatypes level 1.
8812 ****************************************************************************/
8814 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8815 union spoolss_PrintProcDataTypesInfo **info_p,
8816 uint32_t *count)
8818 WERROR result;
8819 union spoolss_PrintProcDataTypesInfo *info;
8821 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8822 W_ERROR_HAVE_NO_MEMORY(info);
8824 *count = 1;
8826 result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8827 if (!W_ERROR_IS_OK(result)) {
8828 goto out;
8831 out:
8832 if (!W_ERROR_IS_OK(result)) {
8833 TALLOC_FREE(info);
8834 *count = 0;
8835 return result;
8838 *info_p = info;
8840 return WERR_OK;
8843 /****************************************************************
8844 _spoolss_EnumPrintProcDataTypes
8845 ****************************************************************/
8847 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
8848 struct spoolss_EnumPrintProcDataTypes *r)
8850 WERROR result;
8852 /* that's an [in out] buffer */
8854 if (!r->in.buffer && (r->in.offered != 0)) {
8855 return WERR_INVALID_PARAM;
8858 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8860 *r->out.count = 0;
8861 *r->out.needed = 0;
8862 *r->out.info = NULL;
8864 if (r->in.print_processor_name == NULL ||
8865 !strequal(r->in.print_processor_name, "winprint")) {
8866 return WERR_UNKNOWN_PRINTPROCESSOR;
8869 switch (r->in.level) {
8870 case 1:
8871 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8872 r->out.count);
8873 break;
8874 default:
8875 return WERR_UNKNOWN_LEVEL;
8878 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8879 spoolss_EnumPrintProcDataTypes,
8880 *r->out.info, r->in.level,
8881 *r->out.count);
8882 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8883 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8885 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8888 /****************************************************************************
8889 fill_monitor_1
8890 ****************************************************************************/
8892 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8893 struct spoolss_MonitorInfo1 *r,
8894 const char *monitor_name)
8896 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8897 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8899 return WERR_OK;
8902 /****************************************************************************
8903 fill_monitor_2
8904 ****************************************************************************/
8906 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8907 struct spoolss_MonitorInfo2 *r,
8908 const char *monitor_name,
8909 const char *environment,
8910 const char *dll_name)
8912 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8913 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8914 r->environment = talloc_strdup(mem_ctx, environment);
8915 W_ERROR_HAVE_NO_MEMORY(r->environment);
8916 r->dll_name = talloc_strdup(mem_ctx, dll_name);
8917 W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8919 return WERR_OK;
8922 /****************************************************************************
8923 enumprintmonitors level 1.
8924 ****************************************************************************/
8926 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8927 union spoolss_MonitorInfo **info_p,
8928 uint32_t *count)
8930 union spoolss_MonitorInfo *info;
8931 WERROR result = WERR_OK;
8933 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8934 W_ERROR_HAVE_NO_MEMORY(info);
8936 *count = 2;
8938 result = fill_monitor_1(info, &info[0].info1,
8939 SPL_LOCAL_PORT);
8940 if (!W_ERROR_IS_OK(result)) {
8941 goto out;
8944 result = fill_monitor_1(info, &info[1].info1,
8945 SPL_TCPIP_PORT);
8946 if (!W_ERROR_IS_OK(result)) {
8947 goto out;
8950 out:
8951 if (!W_ERROR_IS_OK(result)) {
8952 TALLOC_FREE(info);
8953 *count = 0;
8954 return result;
8957 *info_p = info;
8959 return WERR_OK;
8962 /****************************************************************************
8963 enumprintmonitors level 2.
8964 ****************************************************************************/
8966 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8967 union spoolss_MonitorInfo **info_p,
8968 uint32_t *count)
8970 union spoolss_MonitorInfo *info;
8971 WERROR result = WERR_OK;
8973 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8974 W_ERROR_HAVE_NO_MEMORY(info);
8976 *count = 2;
8978 result = fill_monitor_2(info, &info[0].info2,
8979 SPL_LOCAL_PORT,
8980 "Windows NT X86", /* FIXME */
8981 "localmon.dll");
8982 if (!W_ERROR_IS_OK(result)) {
8983 goto out;
8986 result = fill_monitor_2(info, &info[1].info2,
8987 SPL_TCPIP_PORT,
8988 "Windows NT X86", /* FIXME */
8989 "tcpmon.dll");
8990 if (!W_ERROR_IS_OK(result)) {
8991 goto out;
8994 out:
8995 if (!W_ERROR_IS_OK(result)) {
8996 TALLOC_FREE(info);
8997 *count = 0;
8998 return result;
9001 *info_p = info;
9003 return WERR_OK;
9006 /****************************************************************
9007 _spoolss_EnumMonitors
9008 ****************************************************************/
9010 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
9011 struct spoolss_EnumMonitors *r)
9013 WERROR result;
9015 /* that's an [in out] buffer */
9017 if (!r->in.buffer && (r->in.offered != 0)) {
9018 return WERR_INVALID_PARAM;
9021 DEBUG(5,("_spoolss_EnumMonitors\n"));
9024 * Enumerate the print monitors ...
9026 * Just reply with "Local Port", to keep NT happy
9027 * and I can use my nice printer checker.
9030 *r->out.count = 0;
9031 *r->out.needed = 0;
9032 *r->out.info = NULL;
9034 switch (r->in.level) {
9035 case 1:
9036 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
9037 r->out.count);
9038 break;
9039 case 2:
9040 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
9041 r->out.count);
9042 break;
9043 default:
9044 return WERR_UNKNOWN_LEVEL;
9047 if (!W_ERROR_IS_OK(result)) {
9048 return result;
9051 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9052 spoolss_EnumMonitors,
9053 *r->out.info, r->in.level,
9054 *r->out.count);
9055 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9056 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9058 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9061 /****************************************************************************
9062 ****************************************************************************/
9064 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
9065 const print_queue_struct *queue,
9066 int count, int snum,
9067 struct spoolss_PrinterInfo2 *pinfo2,
9068 uint32_t jobid,
9069 struct spoolss_JobInfo1 *r)
9071 int i = 0;
9072 bool found = false;
9074 for (i=0; i<count; i++) {
9075 if (queue[i].job == (int)jobid) {
9076 found = true;
9077 break;
9081 if (found == false) {
9082 /* NT treats not found as bad param... yet another bad choice */
9083 return WERR_INVALID_PARAM;
9086 return fill_job_info1(mem_ctx,
9088 &queue[i],
9090 snum,
9091 pinfo2);
9094 /****************************************************************************
9095 ****************************************************************************/
9097 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9098 const print_queue_struct *queue,
9099 int count, int snum,
9100 struct spoolss_PrinterInfo2 *pinfo2,
9101 uint32_t jobid,
9102 struct spoolss_JobInfo2 *r)
9104 int i = 0;
9105 bool found = false;
9106 struct spoolss_DeviceMode *devmode;
9107 WERROR result;
9109 for (i=0; i<count; i++) {
9110 if (queue[i].job == (int)jobid) {
9111 found = true;
9112 break;
9116 if (found == false) {
9117 /* NT treats not found as bad param... yet another bad
9118 choice */
9119 return WERR_INVALID_PARAM;
9123 * if the print job does not have a DEVMODE associated with it,
9124 * just use the one for the printer. A NULL devicemode is not
9125 * a failure condition
9128 devmode = print_job_devmode(lp_const_servicename(snum), jobid);
9129 if (!devmode) {
9130 result = spoolss_create_default_devmode(mem_ctx,
9131 pinfo2->printername,
9132 &devmode);
9133 if (!W_ERROR_IS_OK(result)) {
9134 DEBUG(3, ("Can't proceed w/o a devmode!"));
9135 return result;
9139 return fill_job_info2(mem_ctx,
9141 &queue[i],
9143 snum,
9144 pinfo2,
9145 devmode);
9148 /****************************************************************
9149 _spoolss_GetJob
9150 ****************************************************************/
9152 WERROR _spoolss_GetJob(struct pipes_struct *p,
9153 struct spoolss_GetJob *r)
9155 WERROR result = WERR_OK;
9156 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9157 int snum;
9158 int count;
9159 print_queue_struct *queue = NULL;
9160 print_status_struct prt_status;
9162 /* that's an [in out] buffer */
9164 if (!r->in.buffer && (r->in.offered != 0)) {
9165 return WERR_INVALID_PARAM;
9168 DEBUG(5,("_spoolss_GetJob\n"));
9170 *r->out.needed = 0;
9172 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9173 return WERR_BADFID;
9176 result = winreg_get_printer_internal(p->mem_ctx,
9177 get_session_info_system(),
9178 p->msg_ctx,
9179 lp_const_servicename(snum),
9180 &pinfo2);
9181 if (!W_ERROR_IS_OK(result)) {
9182 return result;
9185 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9187 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9188 count, prt_status.status, prt_status.message));
9190 switch (r->in.level) {
9191 case 1:
9192 result = getjob_level_1(p->mem_ctx,
9193 queue, count, snum, pinfo2,
9194 r->in.job_id, &r->out.info->info1);
9195 break;
9196 case 2:
9197 result = getjob_level_2(p->mem_ctx,
9198 queue, count, snum, pinfo2,
9199 r->in.job_id, &r->out.info->info2);
9200 break;
9201 default:
9202 result = WERR_UNKNOWN_LEVEL;
9203 break;
9206 SAFE_FREE(queue);
9207 TALLOC_FREE(pinfo2);
9209 if (!W_ERROR_IS_OK(result)) {
9210 TALLOC_FREE(r->out.info);
9211 return result;
9214 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9215 r->in.level);
9216 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9218 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9221 /****************************************************************
9222 _spoolss_GetPrinterDataEx
9223 ****************************************************************/
9225 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9226 struct spoolss_GetPrinterDataEx *r)
9229 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9230 const char *printer;
9231 int snum = 0;
9232 WERROR result = WERR_OK;
9233 DATA_BLOB blob;
9234 enum winreg_Type val_type = REG_NONE;
9235 uint8_t *val_data = NULL;
9236 uint32_t val_size = 0;
9237 struct dcerpc_binding_handle *b;
9239 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9241 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9242 r->in.key_name, r->in.value_name));
9244 /* in case of problem, return some default values */
9246 *r->out.needed = 0;
9247 *r->out.type = REG_NONE;
9249 if (!Printer) {
9250 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9251 OUR_HANDLE(r->in.handle)));
9252 result = WERR_BADFID;
9253 goto done;
9256 /* Is the handle to a printer or to the server? */
9258 if (Printer->printer_type == SPLHND_SERVER) {
9260 union spoolss_PrinterData data;
9262 result = getprinterdata_printer_server(p->mem_ctx,
9263 r->in.value_name,
9264 r->out.type,
9265 &data);
9266 if (!W_ERROR_IS_OK(result)) {
9267 return result;
9270 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
9271 *r->out.type, &data);
9272 if (!W_ERROR_IS_OK(result)) {
9273 return result;
9276 *r->out.needed = blob.length;
9278 if (r->in.offered >= *r->out.needed) {
9279 memcpy(r->out.data, blob.data, blob.length);
9282 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9285 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9286 return WERR_BADFID;
9288 printer = lp_const_servicename(snum);
9290 /* check to see if the keyname is valid */
9291 if (!strlen(r->in.key_name)) {
9292 return WERR_INVALID_PARAM;
9295 result = winreg_printer_binding_handle(p->mem_ctx,
9296 get_session_info_system(),
9297 p->msg_ctx,
9298 &b);
9299 if (!W_ERROR_IS_OK(result)) {
9300 return result;
9303 /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9304 if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9305 strequal(r->in.value_name, "ChangeId")) {
9306 *r->out.type = REG_DWORD;
9307 *r->out.needed = 4;
9308 if (r->in.offered >= *r->out.needed) {
9309 uint32_t changeid = 0;
9311 result = winreg_printer_get_changeid(p->mem_ctx, b,
9312 printer,
9313 &changeid);
9314 if (!W_ERROR_IS_OK(result)) {
9315 return result;
9318 SIVAL(r->out.data, 0, changeid);
9319 result = WERR_OK;
9321 goto done;
9324 result = winreg_get_printer_dataex(p->mem_ctx, b,
9325 printer,
9326 r->in.key_name,
9327 r->in.value_name,
9328 &val_type,
9329 &val_data,
9330 &val_size);
9331 if (!W_ERROR_IS_OK(result)) {
9332 return result;
9335 *r->out.needed = val_size;
9336 *r->out.type = val_type;
9338 if (r->in.offered >= *r->out.needed) {
9339 memcpy(r->out.data, val_data, val_size);
9342 done:
9343 /* retain type when returning WERR_MORE_DATA */
9344 r->out.data = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
9346 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9349 /****************************************************************
9350 _spoolss_SetPrinterDataEx
9351 ****************************************************************/
9353 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9354 struct spoolss_SetPrinterDataEx *r)
9356 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9357 int snum = 0;
9358 WERROR result = WERR_OK;
9359 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9360 char *oid_string;
9361 struct dcerpc_binding_handle *b;
9363 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9365 /* From MSDN documentation of SetPrinterDataEx: pass request to
9366 SetPrinterData if key is "PrinterDriverData" */
9368 if (!Printer) {
9369 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9370 OUR_HANDLE(r->in.handle)));
9371 return WERR_BADFID;
9374 if (Printer->printer_type == SPLHND_SERVER) {
9375 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9376 "Not implemented for server handles yet\n"));
9377 return WERR_INVALID_PARAM;
9380 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9381 return WERR_BADFID;
9385 * Access check : NT returns "access denied" if you make a
9386 * SetPrinterData call without the necessary privildge.
9387 * we were originally returning OK if nothing changed
9388 * which made Win2k issue **a lot** of SetPrinterData
9389 * when connecting to a printer --jerry
9392 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9393 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9394 "change denied by handle access permissions\n"));
9395 return WERR_ACCESS_DENIED;
9398 result = winreg_printer_binding_handle(p->mem_ctx,
9399 get_session_info_system(),
9400 p->msg_ctx,
9401 &b);
9402 if (!W_ERROR_IS_OK(result)) {
9403 return result;
9406 result = winreg_get_printer(Printer, b,
9407 lp_servicename(snum),
9408 &pinfo2);
9409 if (!W_ERROR_IS_OK(result)) {
9410 return result;
9413 /* check for OID in valuename */
9415 oid_string = strchr(r->in.value_name, ',');
9416 if (oid_string) {
9417 *oid_string = '\0';
9418 oid_string++;
9421 /* save the registry data */
9423 result = winreg_set_printer_dataex(p->mem_ctx, b,
9424 pinfo2->sharename,
9425 r->in.key_name,
9426 r->in.value_name,
9427 r->in.type,
9428 r->in.data,
9429 r->in.offered);
9431 if (W_ERROR_IS_OK(result)) {
9432 /* save the OID if one was specified */
9433 if (oid_string) {
9434 char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9435 r->in.key_name, SPOOL_OID_KEY);
9436 if (!str) {
9437 result = WERR_NOMEM;
9438 goto done;
9442 * I'm not checking the status here on purpose. Don't know
9443 * if this is right, but I'm returning the status from the
9444 * previous set_printer_dataex() call. I have no idea if
9445 * this is right. --jerry
9447 winreg_set_printer_dataex(p->mem_ctx, b,
9448 pinfo2->sharename,
9449 str,
9450 r->in.value_name,
9451 REG_SZ,
9452 (uint8_t *) oid_string,
9453 strlen(oid_string) + 1);
9456 result = winreg_printer_update_changeid(p->mem_ctx, b,
9457 lp_const_servicename(snum));
9461 done:
9462 talloc_free(pinfo2);
9463 return result;
9466 /****************************************************************
9467 _spoolss_DeletePrinterDataEx
9468 ****************************************************************/
9470 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9471 struct spoolss_DeletePrinterDataEx *r)
9473 const char *printer;
9474 int snum=0;
9475 WERROR status = WERR_OK;
9476 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9478 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9480 if (!Printer) {
9481 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9482 "Invalid handle (%s:%u:%u).\n",
9483 OUR_HANDLE(r->in.handle)));
9484 return WERR_BADFID;
9487 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9488 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9489 "printer properties change denied by handle\n"));
9490 return WERR_ACCESS_DENIED;
9493 if (!r->in.value_name || !r->in.key_name) {
9494 return WERR_NOMEM;
9497 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9498 return WERR_BADFID;
9500 printer = lp_const_servicename(snum);
9502 status = winreg_delete_printer_dataex_internal(p->mem_ctx,
9503 get_session_info_system(),
9504 p->msg_ctx,
9505 printer,
9506 r->in.key_name,
9507 r->in.value_name);
9508 if (W_ERROR_IS_OK(status)) {
9509 status = winreg_printer_update_changeid_internal(p->mem_ctx,
9510 get_session_info_system(),
9511 p->msg_ctx,
9512 printer);
9515 return status;
9518 /****************************************************************
9519 _spoolss_EnumPrinterKey
9520 ****************************************************************/
9522 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9523 struct spoolss_EnumPrinterKey *r)
9525 uint32_t num_keys;
9526 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9527 int snum = 0;
9528 WERROR result = WERR_BADFILE;
9529 const char **array = NULL;
9530 DATA_BLOB blob;
9532 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9534 if (!Printer) {
9535 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9536 OUR_HANDLE(r->in.handle)));
9537 return WERR_BADFID;
9540 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9541 return WERR_BADFID;
9544 result = winreg_enum_printer_key_internal(p->mem_ctx,
9545 get_session_info_system(),
9546 p->msg_ctx,
9547 lp_const_servicename(snum),
9548 r->in.key_name,
9549 &num_keys,
9550 &array);
9551 if (!W_ERROR_IS_OK(result)) {
9552 goto done;
9555 if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9556 result = WERR_NOMEM;
9557 goto done;
9560 *r->out._ndr_size = r->in.offered / 2;
9561 *r->out.needed = blob.length;
9563 if (r->in.offered < *r->out.needed) {
9564 result = WERR_MORE_DATA;
9565 } else {
9566 result = WERR_OK;
9567 r->out.key_buffer->string_array = array;
9570 done:
9571 if (!W_ERROR_IS_OK(result)) {
9572 TALLOC_FREE(array);
9573 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9574 *r->out.needed = 0;
9578 return result;
9581 /****************************************************************
9582 _spoolss_DeletePrinterKey
9583 ****************************************************************/
9585 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9586 struct spoolss_DeletePrinterKey *r)
9588 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9589 int snum=0;
9590 WERROR status;
9591 const char *printer;
9592 struct dcerpc_binding_handle *b;
9594 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9596 if (!Printer) {
9597 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9598 OUR_HANDLE(r->in.handle)));
9599 return WERR_BADFID;
9602 /* if keyname == NULL, return error */
9603 if ( !r->in.key_name )
9604 return WERR_INVALID_PARAM;
9606 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9607 return WERR_BADFID;
9610 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9611 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9612 "printer properties change denied by handle\n"));
9613 return WERR_ACCESS_DENIED;
9616 printer = lp_const_servicename(snum);
9618 status = winreg_printer_binding_handle(p->mem_ctx,
9619 get_session_info_system(),
9620 p->msg_ctx,
9621 &b);
9622 if (!W_ERROR_IS_OK(status)) {
9623 return status;
9626 /* delete the key and all subkeys */
9627 status = winreg_delete_printer_key(p->mem_ctx, b,
9628 printer,
9629 r->in.key_name);
9630 if (W_ERROR_IS_OK(status)) {
9631 status = winreg_printer_update_changeid(p->mem_ctx, b,
9632 printer);
9635 return status;
9638 /****************************************************************
9639 _spoolss_EnumPrinterDataEx
9640 ****************************************************************/
9642 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
9643 struct spoolss_EnumPrinterDataEx *r)
9645 uint32_t count = 0;
9646 struct spoolss_PrinterEnumValues *info = NULL;
9647 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9648 int snum;
9649 WERROR result;
9651 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9653 *r->out.count = 0;
9654 *r->out.needed = 0;
9655 *r->out.info = NULL;
9657 if (!Printer) {
9658 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9659 OUR_HANDLE(r->in.handle)));
9660 return WERR_BADFID;
9664 * first check for a keyname of NULL or "". Win2k seems to send
9665 * this a lot and we should send back WERR_INVALID_PARAM
9666 * no need to spend time looking up the printer in this case.
9667 * --jerry
9670 if (!strlen(r->in.key_name)) {
9671 result = WERR_INVALID_PARAM;
9672 goto done;
9675 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9676 return WERR_BADFID;
9679 /* now look for a match on the key name */
9680 result = winreg_enum_printer_dataex_internal(p->mem_ctx,
9681 get_session_info_system(),
9682 p->msg_ctx,
9683 lp_const_servicename(snum),
9684 r->in.key_name,
9685 &count,
9686 &info);
9687 if (!W_ERROR_IS_OK(result)) {
9688 goto done;
9691 #if 0 /* FIXME - gd */
9692 /* housekeeping information in the reply */
9694 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9695 * the hand marshalled container size is a multiple
9696 * of 4 bytes for RPC alignment.
9699 if (needed % 4) {
9700 needed += 4-(needed % 4);
9702 #endif
9703 *r->out.count = count;
9704 *r->out.info = info;
9706 done:
9707 if (!W_ERROR_IS_OK(result)) {
9708 return result;
9711 *r->out.needed = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9712 spoolss_EnumPrinterDataEx,
9713 *r->out.info,
9714 *r->out.count);
9715 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9716 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9718 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9721 /****************************************************************************
9722 ****************************************************************************/
9724 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9725 const char *servername,
9726 const char *environment,
9727 struct spoolss_PrintProcessorDirectoryInfo1 *r)
9729 WERROR werr;
9730 char *path = NULL;
9732 werr = compose_spoolss_server_path(mem_ctx,
9733 servername,
9734 environment,
9735 SPOOLSS_PRTPROCS_PATH,
9736 &path);
9737 if (!W_ERROR_IS_OK(werr)) {
9738 return werr;
9741 DEBUG(4,("print processor directory: [%s]\n", path));
9743 r->directory_name = path;
9745 return WERR_OK;
9748 /****************************************************************
9749 _spoolss_GetPrintProcessorDirectory
9750 ****************************************************************/
9752 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
9753 struct spoolss_GetPrintProcessorDirectory *r)
9755 WERROR result;
9756 char *prnproc_share = NULL;
9757 bool prnproc_share_exists = false;
9758 int snum;
9760 /* that's an [in out] buffer */
9762 if (!r->in.buffer && (r->in.offered != 0)) {
9763 return WERR_INVALID_PARAM;
9766 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9767 r->in.level));
9769 *r->out.needed = 0;
9771 /* r->in.level is ignored */
9773 /* We always should reply with a local print processor directory so that
9774 * users are not forced to have a [prnproc$] share on the Samba spoolss
9775 * server, if users decide to do so, lets announce it though - Guenther */
9777 snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
9778 if (!prnproc_share) {
9779 return WERR_NOMEM;
9781 if (snum != -1) {
9782 prnproc_share_exists = true;
9785 result = getprintprocessordirectory_level_1(p->mem_ctx,
9786 prnproc_share_exists ? r->in.server : NULL,
9787 r->in.environment,
9788 &r->out.info->info1);
9789 if (!W_ERROR_IS_OK(result)) {
9790 TALLOC_FREE(r->out.info);
9791 return result;
9794 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
9795 r->out.info, r->in.level);
9796 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9798 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9801 /*******************************************************************
9802 ********************************************************************/
9804 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9805 const char *dllname)
9807 enum ndr_err_code ndr_err;
9808 struct spoolss_MonitorUi ui;
9810 ui.dll_name = dllname;
9812 ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
9813 (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9814 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9815 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9817 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9820 /*******************************************************************
9821 Streams the monitor UI DLL name in UNICODE
9822 *******************************************************************/
9824 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9825 struct security_token *token, DATA_BLOB *in,
9826 DATA_BLOB *out, uint32_t *needed)
9828 const char *dllname = "tcpmonui.dll";
9830 *needed = (strlen(dllname)+1) * 2;
9832 if (out->length < *needed) {
9833 return WERR_INSUFFICIENT_BUFFER;
9836 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9837 return WERR_NOMEM;
9840 return WERR_OK;
9843 /*******************************************************************
9844 ********************************************************************/
9846 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9847 struct spoolss_PortData1 *port1,
9848 const DATA_BLOB *buf)
9850 enum ndr_err_code ndr_err;
9851 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
9852 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9853 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9854 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9856 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9859 /*******************************************************************
9860 ********************************************************************/
9862 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9863 struct spoolss_PortData2 *port2,
9864 const DATA_BLOB *buf)
9866 enum ndr_err_code ndr_err;
9867 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
9868 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9869 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9870 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9872 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9875 /*******************************************************************
9876 Create a new TCP/IP port
9877 *******************************************************************/
9879 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9880 struct security_token *token, DATA_BLOB *in,
9881 DATA_BLOB *out, uint32_t *needed)
9883 struct spoolss_PortData1 port1;
9884 struct spoolss_PortData2 port2;
9885 char *device_uri = NULL;
9886 uint32_t version;
9888 const char *portname;
9889 const char *hostaddress;
9890 const char *queue;
9891 uint32_t port_number;
9892 uint32_t protocol;
9894 /* peek for spoolss_PortData version */
9896 if (!in || (in->length < (128 + 4))) {
9897 return WERR_GENERAL_FAILURE;
9900 version = IVAL(in->data, 128);
9902 switch (version) {
9903 case 1:
9904 ZERO_STRUCT(port1);
9906 if (!pull_port_data_1(mem_ctx, &port1, in)) {
9907 return WERR_NOMEM;
9910 portname = port1.portname;
9911 hostaddress = port1.hostaddress;
9912 queue = port1.queue;
9913 protocol = port1.protocol;
9914 port_number = port1.port_number;
9916 break;
9917 case 2:
9918 ZERO_STRUCT(port2);
9920 if (!pull_port_data_2(mem_ctx, &port2, in)) {
9921 return WERR_NOMEM;
9924 portname = port2.portname;
9925 hostaddress = port2.hostaddress;
9926 queue = port2.queue;
9927 protocol = port2.protocol;
9928 port_number = port2.port_number;
9930 break;
9931 default:
9932 DEBUG(1,("xcvtcp_addport: "
9933 "unknown version of port_data: %d\n", version));
9934 return WERR_UNKNOWN_PORT;
9937 /* create the device URI and call the add_port_hook() */
9939 switch (protocol) {
9940 case PROTOCOL_RAWTCP_TYPE:
9941 device_uri = talloc_asprintf(mem_ctx,
9942 "socket://%s:%d/", hostaddress,
9943 port_number);
9944 break;
9946 case PROTOCOL_LPR_TYPE:
9947 device_uri = talloc_asprintf(mem_ctx,
9948 "lpr://%s/%s", hostaddress, queue );
9949 break;
9951 default:
9952 return WERR_UNKNOWN_PORT;
9955 if (!device_uri) {
9956 return WERR_NOMEM;
9959 return add_port_hook(mem_ctx, token, portname, device_uri);
9962 /*******************************************************************
9963 *******************************************************************/
9965 struct xcv_api_table xcvtcp_cmds[] = {
9966 { "MonitorUI", xcvtcp_monitorui },
9967 { "AddPort", xcvtcp_addport},
9968 { NULL, NULL }
9971 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9972 struct security_token *token, const char *command,
9973 DATA_BLOB *inbuf,
9974 DATA_BLOB *outbuf,
9975 uint32_t *needed )
9977 int i;
9979 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9981 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9982 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9983 return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9986 return WERR_BADFUNC;
9989 /*******************************************************************
9990 *******************************************************************/
9991 #if 0 /* don't support management using the "Local Port" monitor */
9993 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9994 struct security_token *token, DATA_BLOB *in,
9995 DATA_BLOB *out, uint32_t *needed)
9997 const char *dllname = "localui.dll";
9999 *needed = (strlen(dllname)+1) * 2;
10001 if (out->length < *needed) {
10002 return WERR_INSUFFICIENT_BUFFER;
10005 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10006 return WERR_NOMEM;
10009 return WERR_OK;
10012 /*******************************************************************
10013 *******************************************************************/
10015 struct xcv_api_table xcvlocal_cmds[] = {
10016 { "MonitorUI", xcvlocal_monitorui },
10017 { NULL, NULL }
10019 #else
10020 struct xcv_api_table xcvlocal_cmds[] = {
10021 { NULL, NULL }
10023 #endif
10027 /*******************************************************************
10028 *******************************************************************/
10030 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
10031 struct security_token *token, const char *command,
10032 DATA_BLOB *inbuf, DATA_BLOB *outbuf,
10033 uint32_t *needed)
10035 int i;
10037 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10039 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10040 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10041 return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10043 return WERR_BADFUNC;
10046 /****************************************************************
10047 _spoolss_XcvData
10048 ****************************************************************/
10050 WERROR _spoolss_XcvData(struct pipes_struct *p,
10051 struct spoolss_XcvData *r)
10053 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10054 DATA_BLOB out_data = data_blob_null;
10055 WERROR werror;
10057 if (!Printer) {
10058 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10059 OUR_HANDLE(r->in.handle)));
10060 return WERR_BADFID;
10063 /* Has to be a handle to the TCP/IP port monitor */
10065 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10066 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10067 return WERR_BADFID;
10070 /* requires administrative access to the server */
10072 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10073 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10074 return WERR_ACCESS_DENIED;
10077 /* Allocate the outgoing buffer */
10079 if (r->in.out_data_size) {
10080 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10081 if (out_data.data == NULL) {
10082 return WERR_NOMEM;
10086 switch ( Printer->printer_type ) {
10087 case SPLHND_PORTMON_TCP:
10088 werror = process_xcvtcp_command(p->mem_ctx,
10089 p->session_info->security_token,
10090 r->in.function_name,
10091 &r->in.in_data, &out_data,
10092 r->out.needed);
10093 break;
10094 case SPLHND_PORTMON_LOCAL:
10095 werror = process_xcvlocal_command(p->mem_ctx,
10096 p->session_info->security_token,
10097 r->in.function_name,
10098 &r->in.in_data, &out_data,
10099 r->out.needed);
10100 break;
10101 default:
10102 werror = WERR_INVALID_PRINT_MONITOR;
10105 if (!W_ERROR_IS_OK(werror)) {
10106 return werror;
10109 *r->out.status_code = 0;
10111 if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10112 memcpy(r->out.out_data, out_data.data,
10113 MIN(r->in.out_data_size, out_data.length));
10116 return WERR_OK;
10119 /****************************************************************
10120 _spoolss_AddPrintProcessor
10121 ****************************************************************/
10123 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10124 struct spoolss_AddPrintProcessor *r)
10126 /* for now, just indicate success and ignore the add. We'll
10127 automatically set the winprint processor for printer
10128 entries later. Used to debug the LexMark Optra S 1855 PCL
10129 driver --jerry */
10131 return WERR_OK;
10134 /****************************************************************
10135 _spoolss_AddPort
10136 ****************************************************************/
10138 WERROR _spoolss_AddPort(struct pipes_struct *p,
10139 struct spoolss_AddPort *r)
10141 /* do what w2k3 does */
10143 return WERR_NOT_SUPPORTED;
10146 /****************************************************************
10147 _spoolss_GetPrinterDriver
10148 ****************************************************************/
10150 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10151 struct spoolss_GetPrinterDriver *r)
10153 p->rng_fault_state = true;
10154 return WERR_NOT_SUPPORTED;
10157 /****************************************************************
10158 _spoolss_ReadPrinter
10159 ****************************************************************/
10161 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10162 struct spoolss_ReadPrinter *r)
10164 p->rng_fault_state = true;
10165 return WERR_NOT_SUPPORTED;
10168 /****************************************************************
10169 _spoolss_WaitForPrinterChange
10170 ****************************************************************/
10172 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10173 struct spoolss_WaitForPrinterChange *r)
10175 p->rng_fault_state = true;
10176 return WERR_NOT_SUPPORTED;
10179 /****************************************************************
10180 _spoolss_ConfigurePort
10181 ****************************************************************/
10183 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10184 struct spoolss_ConfigurePort *r)
10186 p->rng_fault_state = true;
10187 return WERR_NOT_SUPPORTED;
10190 /****************************************************************
10191 _spoolss_DeletePort
10192 ****************************************************************/
10194 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10195 struct spoolss_DeletePort *r)
10197 p->rng_fault_state = true;
10198 return WERR_NOT_SUPPORTED;
10201 /****************************************************************
10202 _spoolss_CreatePrinterIC
10203 ****************************************************************/
10205 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10206 struct spoolss_CreatePrinterIC *r)
10208 p->rng_fault_state = true;
10209 return WERR_NOT_SUPPORTED;
10212 /****************************************************************
10213 _spoolss_PlayGDIScriptOnPrinterIC
10214 ****************************************************************/
10216 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10217 struct spoolss_PlayGDIScriptOnPrinterIC *r)
10219 p->rng_fault_state = true;
10220 return WERR_NOT_SUPPORTED;
10223 /****************************************************************
10224 _spoolss_DeletePrinterIC
10225 ****************************************************************/
10227 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10228 struct spoolss_DeletePrinterIC *r)
10230 p->rng_fault_state = true;
10231 return WERR_NOT_SUPPORTED;
10234 /****************************************************************
10235 _spoolss_AddPrinterConnection
10236 ****************************************************************/
10238 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10239 struct spoolss_AddPrinterConnection *r)
10241 p->rng_fault_state = true;
10242 return WERR_NOT_SUPPORTED;
10245 /****************************************************************
10246 _spoolss_DeletePrinterConnection
10247 ****************************************************************/
10249 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10250 struct spoolss_DeletePrinterConnection *r)
10252 p->rng_fault_state = true;
10253 return WERR_NOT_SUPPORTED;
10256 /****************************************************************
10257 _spoolss_PrinterMessageBox
10258 ****************************************************************/
10260 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10261 struct spoolss_PrinterMessageBox *r)
10263 p->rng_fault_state = true;
10264 return WERR_NOT_SUPPORTED;
10267 /****************************************************************
10268 _spoolss_AddMonitor
10269 ****************************************************************/
10271 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10272 struct spoolss_AddMonitor *r)
10274 p->rng_fault_state = true;
10275 return WERR_NOT_SUPPORTED;
10278 /****************************************************************
10279 _spoolss_DeleteMonitor
10280 ****************************************************************/
10282 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10283 struct spoolss_DeleteMonitor *r)
10285 p->rng_fault_state = true;
10286 return WERR_NOT_SUPPORTED;
10289 /****************************************************************
10290 _spoolss_DeletePrintProcessor
10291 ****************************************************************/
10293 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10294 struct spoolss_DeletePrintProcessor *r)
10296 p->rng_fault_state = true;
10297 return WERR_NOT_SUPPORTED;
10300 /****************************************************************
10301 _spoolss_AddPrintProvidor
10302 ****************************************************************/
10304 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10305 struct spoolss_AddPrintProvidor *r)
10307 p->rng_fault_state = true;
10308 return WERR_NOT_SUPPORTED;
10311 /****************************************************************
10312 _spoolss_DeletePrintProvidor
10313 ****************************************************************/
10315 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10316 struct spoolss_DeletePrintProvidor *r)
10318 p->rng_fault_state = true;
10319 return WERR_NOT_SUPPORTED;
10322 /****************************************************************
10323 _spoolss_FindFirstPrinterChangeNotification
10324 ****************************************************************/
10326 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10327 struct spoolss_FindFirstPrinterChangeNotification *r)
10329 p->rng_fault_state = true;
10330 return WERR_NOT_SUPPORTED;
10333 /****************************************************************
10334 _spoolss_FindNextPrinterChangeNotification
10335 ****************************************************************/
10337 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10338 struct spoolss_FindNextPrinterChangeNotification *r)
10340 p->rng_fault_state = true;
10341 return WERR_NOT_SUPPORTED;
10344 /****************************************************************
10345 _spoolss_RouterFindFirstPrinterChangeNotificationOld
10346 ****************************************************************/
10348 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10349 struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10351 p->rng_fault_state = true;
10352 return WERR_NOT_SUPPORTED;
10355 /****************************************************************
10356 _spoolss_ReplyOpenPrinter
10357 ****************************************************************/
10359 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10360 struct spoolss_ReplyOpenPrinter *r)
10362 p->rng_fault_state = true;
10363 return WERR_NOT_SUPPORTED;
10366 /****************************************************************
10367 _spoolss_RouterReplyPrinter
10368 ****************************************************************/
10370 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10371 struct spoolss_RouterReplyPrinter *r)
10373 p->rng_fault_state = true;
10374 return WERR_NOT_SUPPORTED;
10377 /****************************************************************
10378 _spoolss_ReplyClosePrinter
10379 ****************************************************************/
10381 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10382 struct spoolss_ReplyClosePrinter *r)
10384 p->rng_fault_state = true;
10385 return WERR_NOT_SUPPORTED;
10388 /****************************************************************
10389 _spoolss_AddPortEx
10390 ****************************************************************/
10392 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10393 struct spoolss_AddPortEx *r)
10395 p->rng_fault_state = true;
10396 return WERR_NOT_SUPPORTED;
10399 /****************************************************************
10400 _spoolss_RouterFindFirstPrinterChangeNotification
10401 ****************************************************************/
10403 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10404 struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10406 p->rng_fault_state = true;
10407 return WERR_NOT_SUPPORTED;
10410 /****************************************************************
10411 _spoolss_SpoolerInit
10412 ****************************************************************/
10414 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10415 struct spoolss_SpoolerInit *r)
10417 p->rng_fault_state = true;
10418 return WERR_NOT_SUPPORTED;
10421 /****************************************************************
10422 _spoolss_ResetPrinterEx
10423 ****************************************************************/
10425 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10426 struct spoolss_ResetPrinterEx *r)
10428 p->rng_fault_state = true;
10429 return WERR_NOT_SUPPORTED;
10432 /****************************************************************
10433 _spoolss_RouterReplyPrinterEx
10434 ****************************************************************/
10436 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10437 struct spoolss_RouterReplyPrinterEx *r)
10439 p->rng_fault_state = true;
10440 return WERR_NOT_SUPPORTED;
10443 /****************************************************************
10444 _spoolss_44
10445 ****************************************************************/
10447 WERROR _spoolss_44(struct pipes_struct *p,
10448 struct spoolss_44 *r)
10450 p->rng_fault_state = true;
10451 return WERR_NOT_SUPPORTED;
10454 /****************************************************************
10455 _spoolss_SetPort
10456 ****************************************************************/
10458 WERROR _spoolss_SetPort(struct pipes_struct *p,
10459 struct spoolss_SetPort *r)
10461 p->rng_fault_state = true;
10462 return WERR_NOT_SUPPORTED;
10465 /****************************************************************
10466 _spoolss_4a
10467 ****************************************************************/
10469 WERROR _spoolss_4a(struct pipes_struct *p,
10470 struct spoolss_4a *r)
10472 p->rng_fault_state = true;
10473 return WERR_NOT_SUPPORTED;
10476 /****************************************************************
10477 _spoolss_4b
10478 ****************************************************************/
10480 WERROR _spoolss_4b(struct pipes_struct *p,
10481 struct spoolss_4b *r)
10483 p->rng_fault_state = true;
10484 return WERR_NOT_SUPPORTED;
10487 /****************************************************************
10488 _spoolss_4c
10489 ****************************************************************/
10491 WERROR _spoolss_4c(struct pipes_struct *p,
10492 struct spoolss_4c *r)
10494 p->rng_fault_state = true;
10495 return WERR_NOT_SUPPORTED;
10498 /****************************************************************
10499 _spoolss_53
10500 ****************************************************************/
10502 WERROR _spoolss_53(struct pipes_struct *p,
10503 struct spoolss_53 *r)
10505 p->rng_fault_state = true;
10506 return WERR_NOT_SUPPORTED;
10509 /****************************************************************
10510 _spoolss_AddPerMachineConnection
10511 ****************************************************************/
10513 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
10514 struct spoolss_AddPerMachineConnection *r)
10516 p->rng_fault_state = true;
10517 return WERR_NOT_SUPPORTED;
10520 /****************************************************************
10521 _spoolss_DeletePerMachineConnection
10522 ****************************************************************/
10524 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
10525 struct spoolss_DeletePerMachineConnection *r)
10527 p->rng_fault_state = true;
10528 return WERR_NOT_SUPPORTED;
10531 /****************************************************************
10532 _spoolss_EnumPerMachineConnections
10533 ****************************************************************/
10535 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
10536 struct spoolss_EnumPerMachineConnections *r)
10538 p->rng_fault_state = true;
10539 return WERR_NOT_SUPPORTED;
10542 /****************************************************************
10543 _spoolss_5a
10544 ****************************************************************/
10546 WERROR _spoolss_5a(struct pipes_struct *p,
10547 struct spoolss_5a *r)
10549 p->rng_fault_state = true;
10550 return WERR_NOT_SUPPORTED;
10553 /****************************************************************
10554 _spoolss_5b
10555 ****************************************************************/
10557 WERROR _spoolss_5b(struct pipes_struct *p,
10558 struct spoolss_5b *r)
10560 p->rng_fault_state = true;
10561 return WERR_NOT_SUPPORTED;
10564 /****************************************************************
10565 _spoolss_5c
10566 ****************************************************************/
10568 WERROR _spoolss_5c(struct pipes_struct *p,
10569 struct spoolss_5c *r)
10571 p->rng_fault_state = true;
10572 return WERR_NOT_SUPPORTED;
10575 /****************************************************************
10576 _spoolss_5d
10577 ****************************************************************/
10579 WERROR _spoolss_5d(struct pipes_struct *p,
10580 struct spoolss_5d *r)
10582 p->rng_fault_state = true;
10583 return WERR_NOT_SUPPORTED;
10586 /****************************************************************
10587 _spoolss_5e
10588 ****************************************************************/
10590 WERROR _spoolss_5e(struct pipes_struct *p,
10591 struct spoolss_5e *r)
10593 p->rng_fault_state = true;
10594 return WERR_NOT_SUPPORTED;
10597 /****************************************************************
10598 _spoolss_5f
10599 ****************************************************************/
10601 WERROR _spoolss_5f(struct pipes_struct *p,
10602 struct spoolss_5f *r)
10604 p->rng_fault_state = true;
10605 return WERR_NOT_SUPPORTED;
10608 /****************************************************************
10609 _spoolss_60
10610 ****************************************************************/
10612 WERROR _spoolss_60(struct pipes_struct *p,
10613 struct spoolss_60 *r)
10615 p->rng_fault_state = true;
10616 return WERR_NOT_SUPPORTED;
10619 /****************************************************************
10620 _spoolss_61
10621 ****************************************************************/
10623 WERROR _spoolss_61(struct pipes_struct *p,
10624 struct spoolss_61 *r)
10626 p->rng_fault_state = true;
10627 return WERR_NOT_SUPPORTED;
10630 /****************************************************************
10631 _spoolss_62
10632 ****************************************************************/
10634 WERROR _spoolss_62(struct pipes_struct *p,
10635 struct spoolss_62 *r)
10637 p->rng_fault_state = true;
10638 return WERR_NOT_SUPPORTED;
10641 /****************************************************************
10642 _spoolss_63
10643 ****************************************************************/
10645 WERROR _spoolss_63(struct pipes_struct *p,
10646 struct spoolss_63 *r)
10648 p->rng_fault_state = true;
10649 return WERR_NOT_SUPPORTED;
10652 /****************************************************************
10653 _spoolss_64
10654 ****************************************************************/
10656 WERROR _spoolss_64(struct pipes_struct *p,
10657 struct spoolss_64 *r)
10659 p->rng_fault_state = true;
10660 return WERR_NOT_SUPPORTED;
10663 /****************************************************************
10664 _spoolss_65
10665 ****************************************************************/
10667 WERROR _spoolss_65(struct pipes_struct *p,
10668 struct spoolss_65 *r)
10670 p->rng_fault_state = true;
10671 return WERR_NOT_SUPPORTED;
10674 /****************************************************************
10675 _spoolss_GetCorePrinterDrivers
10676 ****************************************************************/
10678 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
10679 struct spoolss_GetCorePrinterDrivers *r)
10681 p->rng_fault_state = true;
10682 return WERR_NOT_SUPPORTED;
10685 /****************************************************************
10686 _spoolss_67
10687 ****************************************************************/
10689 WERROR _spoolss_67(struct pipes_struct *p,
10690 struct spoolss_67 *r)
10692 p->rng_fault_state = true;
10693 return WERR_NOT_SUPPORTED;
10696 /****************************************************************
10697 _spoolss_GetPrinterDriverPackagePath
10698 ****************************************************************/
10700 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
10701 struct spoolss_GetPrinterDriverPackagePath *r)
10703 p->rng_fault_state = true;
10704 return WERR_NOT_SUPPORTED;
10707 /****************************************************************
10708 _spoolss_69
10709 ****************************************************************/
10711 WERROR _spoolss_69(struct pipes_struct *p,
10712 struct spoolss_69 *r)
10714 p->rng_fault_state = true;
10715 return WERR_NOT_SUPPORTED;
10718 /****************************************************************
10719 _spoolss_6a
10720 ****************************************************************/
10722 WERROR _spoolss_6a(struct pipes_struct *p,
10723 struct spoolss_6a *r)
10725 p->rng_fault_state = true;
10726 return WERR_NOT_SUPPORTED;
10729 /****************************************************************
10730 _spoolss_6b
10731 ****************************************************************/
10733 WERROR _spoolss_6b(struct pipes_struct *p,
10734 struct spoolss_6b *r)
10736 p->rng_fault_state = true;
10737 return WERR_NOT_SUPPORTED;
10740 /****************************************************************
10741 _spoolss_6c
10742 ****************************************************************/
10744 WERROR _spoolss_6c(struct pipes_struct *p,
10745 struct spoolss_6c *r)
10747 p->rng_fault_state = true;
10748 return WERR_NOT_SUPPORTED;
10751 /****************************************************************
10752 _spoolss_6d
10753 ****************************************************************/
10755 WERROR _spoolss_6d(struct pipes_struct *p,
10756 struct spoolss_6d *r)
10758 p->rng_fault_state = true;
10759 return WERR_NOT_SUPPORTED;