s3-spoolss: Pass the right pointer type.
[Samba.git] / source3 / rpc_server / spoolss / srv_spoolss_nt.c
blob4cc06597b92d92ffa2c84a2f91b644424efd09a1
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 const int drv_cversion[] = {SPOOLSS_DRIVER_VERSION_9X,
2046 SPOOLSS_DRIVER_VERSION_NT35,
2047 SPOOLSS_DRIVER_VERSION_NT4,
2048 SPOOLSS_DRIVER_VERSION_200X,
2049 -1};
2051 static int get_version_id(const char *arch)
2053 int i;
2055 for (i=0; archi_table[i].long_archi != NULL; i++)
2057 if (strcmp(arch, archi_table[i].long_archi) == 0)
2058 return (archi_table[i].version);
2061 return -1;
2064 /****************************************************************
2065 _spoolss_DeletePrinterDriver
2066 ****************************************************************/
2068 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2069 struct spoolss_DeletePrinterDriver *r)
2072 struct spoolss_DriverInfo8 *info = NULL;
2073 int version;
2074 WERROR status;
2075 struct dcerpc_binding_handle *b;
2076 TALLOC_CTX *tmp_ctx = NULL;
2077 int i;
2078 bool found;
2080 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2081 and not a printer admin, then fail */
2083 if ( (p->session_info->utok.uid != sec_initial_uid())
2084 && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2085 && !token_contains_name_in_list(
2086 uidtoname(p->session_info->utok.uid),
2087 p->session_info->info3->base.domain.string,
2088 NULL,
2089 p->session_info->security_token,
2090 lp_printer_admin(-1)) )
2092 return WERR_ACCESS_DENIED;
2095 /* check that we have a valid driver name first */
2097 if ((version = get_version_id(r->in.architecture)) == -1)
2098 return WERR_INVALID_ENVIRONMENT;
2100 tmp_ctx = talloc_new(p->mem_ctx);
2101 if (!tmp_ctx) {
2102 return WERR_NOMEM;
2105 status = winreg_printer_binding_handle(tmp_ctx,
2106 get_session_info_system(),
2107 p->msg_ctx,
2108 &b);
2109 if (!W_ERROR_IS_OK(status)) {
2110 goto done;
2113 for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2114 status = winreg_get_driver(tmp_ctx, b,
2115 r->in.architecture, r->in.driver,
2116 drv_cversion[i], &info);
2117 if (!W_ERROR_IS_OK(status)) {
2118 DEBUG(5, ("skipping del of driver with version %d\n",
2119 drv_cversion[i]));
2120 continue;
2122 found = true;
2124 if (printer_driver_in_use(tmp_ctx, get_session_info_system(),
2125 p->msg_ctx, info)) {
2126 status = WERR_PRINTER_DRIVER_IN_USE;
2127 goto done;
2130 status = winreg_del_driver(tmp_ctx, b, info, drv_cversion[i]);
2131 if (!W_ERROR_IS_OK(status)) {
2132 DEBUG(0, ("failed del of driver with version %d\n",
2133 drv_cversion[i]));
2134 goto done;
2137 if (found == false) {
2138 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2139 status = WERR_UNKNOWN_PRINTER_DRIVER;
2140 } else {
2141 status = WERR_OK;
2144 done:
2145 talloc_free(tmp_ctx);
2146 return status;
2149 static WERROR spoolss_dpd_version(TALLOC_CTX *mem_ctx,
2150 struct pipes_struct *p,
2151 struct spoolss_DeletePrinterDriverEx *r,
2152 struct dcerpc_binding_handle *b,
2153 struct spoolss_DriverInfo8 *info)
2155 WERROR status;
2156 bool delete_files;
2158 if (printer_driver_in_use(mem_ctx, get_session_info_system(),
2159 p->msg_ctx, info)) {
2160 status = WERR_PRINTER_DRIVER_IN_USE;
2161 goto done;
2165 * we have a couple of cases to consider.
2166 * (1) Are any files in use? If so and DPD_DELETE_ALL_FILES is set,
2167 * then the delete should fail if **any** files overlap with
2168 * other drivers
2169 * (2) If DPD_DELETE_UNUSED_FILES is set, then delete all
2170 * non-overlapping files
2171 * (3) If neither DPD_DELETE_ALL_FILES nor DPD_DELETE_UNUSED_FILES
2172 * is set, then do not delete any files
2173 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2176 delete_files = r->in.delete_flags
2177 & (DPD_DELETE_ALL_FILES | DPD_DELETE_UNUSED_FILES);
2179 if (delete_files) {
2180 bool in_use = printer_driver_files_in_use(mem_ctx,
2181 get_session_info_system(),
2182 p->msg_ctx,
2183 info);
2184 if (in_use && (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
2185 status = WERR_PRINTER_DRIVER_IN_USE;
2186 goto done;
2189 * printer_driver_files_in_use() has trimmed overlapping files
2190 * from info so they are not removed on DPD_DELETE_UNUSED_FILES
2194 status = winreg_del_driver(mem_ctx, b, info, info->version);
2195 if (!W_ERROR_IS_OK(status)) {
2196 goto done;
2200 * now delete any associated files if delete_files is
2201 * true. Even if this part failes, we return succes
2202 * because the driver doesn not exist any more
2204 if (delete_files) {
2205 delete_driver_files(get_session_info_system(), info);
2208 done:
2209 return status;
2212 /****************************************************************
2213 _spoolss_DeletePrinterDriverEx
2214 ****************************************************************/
2216 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2217 struct spoolss_DeletePrinterDriverEx *r)
2219 struct spoolss_DriverInfo8 *info = NULL;
2220 WERROR status;
2221 struct dcerpc_binding_handle *b;
2222 TALLOC_CTX *tmp_ctx = NULL;
2223 int i;
2224 bool found;
2226 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2227 and not a printer admin, then fail */
2229 if ( (p->session_info->utok.uid != sec_initial_uid())
2230 && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2231 && !token_contains_name_in_list(
2232 uidtoname(p->session_info->utok.uid),
2233 p->session_info->info3->base.domain.string,
2234 NULL,
2235 p->session_info->security_token, lp_printer_admin(-1)) )
2237 return WERR_ACCESS_DENIED;
2240 /* check that we have a valid driver name first */
2241 if (get_version_id(r->in.architecture) == -1) {
2242 /* this is what NT returns */
2243 return WERR_INVALID_ENVIRONMENT;
2246 tmp_ctx = talloc_new(p->mem_ctx);
2247 if (!tmp_ctx) {
2248 return WERR_NOMEM;
2251 status = winreg_printer_binding_handle(tmp_ctx,
2252 get_session_info_system(),
2253 p->msg_ctx,
2254 &b);
2255 if (!W_ERROR_IS_OK(status)) {
2256 goto done;
2259 for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2260 if ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2261 && (drv_cversion[i] != r->in.version)) {
2262 continue;
2265 /* check if a driver with this version exists before delete */
2266 status = winreg_get_driver(tmp_ctx, b,
2267 r->in.architecture, r->in.driver,
2268 drv_cversion[i], &info);
2269 if (!W_ERROR_IS_OK(status)) {
2270 DEBUG(5, ("skipping del of driver with version %d\n",
2271 drv_cversion[i]));
2272 continue;
2274 found = true;
2276 status = spoolss_dpd_version(tmp_ctx, p, r, b, info);
2277 if (!W_ERROR_IS_OK(status)) {
2278 DEBUG(0, ("failed to delete driver with version %d\n",
2279 drv_cversion[i]));
2280 goto done;
2283 if (found == false) {
2284 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2285 status = WERR_UNKNOWN_PRINTER_DRIVER;
2286 } else {
2287 status = WERR_OK;
2290 done:
2291 talloc_free(tmp_ctx);
2292 return status;
2296 /********************************************************************
2297 GetPrinterData on a printer server Handle.
2298 ********************************************************************/
2300 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2301 const char *value,
2302 enum winreg_Type *type,
2303 union spoolss_PrinterData *data)
2305 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2307 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2308 *type = REG_DWORD;
2309 data->value = 0x00;
2310 return WERR_OK;
2313 if (!StrCaseCmp(value, "BeepEnabled")) {
2314 *type = REG_DWORD;
2315 data->value = 0x00;
2316 return WERR_OK;
2319 if (!StrCaseCmp(value, "EventLog")) {
2320 *type = REG_DWORD;
2321 /* formally was 0x1b */
2322 data->value = 0x00;
2323 return WERR_OK;
2326 if (!StrCaseCmp(value, "NetPopup")) {
2327 *type = REG_DWORD;
2328 data->value = 0x00;
2329 return WERR_OK;
2332 if (!StrCaseCmp(value, "MajorVersion")) {
2333 *type = REG_DWORD;
2335 /* Windows NT 4.0 seems to not allow uploading of drivers
2336 to a server that reports 0x3 as the MajorVersion.
2337 need to investigate more how Win2k gets around this .
2338 -- jerry */
2340 if (RA_WINNT == get_remote_arch()) {
2341 data->value = 0x02;
2342 } else {
2343 data->value = 0x03;
2346 return WERR_OK;
2349 if (!StrCaseCmp(value, "MinorVersion")) {
2350 *type = REG_DWORD;
2351 data->value = 0x00;
2352 return WERR_OK;
2355 /* REG_BINARY
2356 * uint32_t size = 0x114
2357 * uint32_t major = 5
2358 * uint32_t minor = [0|1]
2359 * uint32_t build = [2195|2600]
2360 * extra unicode string = e.g. "Service Pack 3"
2362 if (!StrCaseCmp(value, "OSVersion")) {
2363 DATA_BLOB blob;
2364 enum ndr_err_code ndr_err;
2365 struct spoolss_OSVersion os;
2367 os.major = 5; /* Windows 2000 == 5.0 */
2368 os.minor = 0;
2369 os.build = 2195; /* build */
2370 os.extra_string = ""; /* leave extra string empty */
2372 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2373 (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2374 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2375 return WERR_GENERAL_FAILURE;
2378 *type = REG_BINARY;
2379 data->binary = blob;
2381 return WERR_OK;
2385 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2386 *type = REG_SZ;
2388 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2389 W_ERROR_HAVE_NO_MEMORY(data->string);
2391 return WERR_OK;
2394 if (!StrCaseCmp(value, "Architecture")) {
2395 *type = REG_SZ;
2396 data->string = talloc_strdup(mem_ctx,
2397 lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2398 W_ERROR_HAVE_NO_MEMORY(data->string);
2400 return WERR_OK;
2403 if (!StrCaseCmp(value, "DsPresent")) {
2404 *type = REG_DWORD;
2406 /* only show the publish check box if we are a
2407 member of a AD domain */
2409 if (lp_security() == SEC_ADS) {
2410 data->value = 0x01;
2411 } else {
2412 data->value = 0x00;
2414 return WERR_OK;
2417 if (!StrCaseCmp(value, "DNSMachineName")) {
2418 const char *hostname = get_mydnsfullname();
2420 if (!hostname) {
2421 return WERR_BADFILE;
2424 *type = REG_SZ;
2425 data->string = talloc_strdup(mem_ctx, hostname);
2426 W_ERROR_HAVE_NO_MEMORY(data->string);
2428 return WERR_OK;
2431 *type = REG_NONE;
2433 return WERR_INVALID_PARAM;
2436 /****************************************************************
2437 _spoolss_GetPrinterData
2438 ****************************************************************/
2440 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2441 struct spoolss_GetPrinterData *r)
2443 struct spoolss_GetPrinterDataEx r2;
2445 r2.in.handle = r->in.handle;
2446 r2.in.key_name = "PrinterDriverData";
2447 r2.in.value_name = r->in.value_name;
2448 r2.in.offered = r->in.offered;
2449 r2.out.type = r->out.type;
2450 r2.out.data = r->out.data;
2451 r2.out.needed = r->out.needed;
2453 return _spoolss_GetPrinterDataEx(p, &r2);
2456 /*********************************************************
2457 Connect to the client machine.
2458 **********************************************************/
2460 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2461 struct sockaddr_storage *client_ss, const char *remote_machine)
2463 NTSTATUS ret;
2464 struct cli_state *the_cli;
2465 struct sockaddr_storage rm_addr;
2466 char addr[INET6_ADDRSTRLEN];
2468 if ( is_zero_addr(client_ss) ) {
2469 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2470 remote_machine));
2471 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2472 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2473 return false;
2475 print_sockaddr(addr, sizeof(addr), &rm_addr);
2476 } else {
2477 rm_addr = *client_ss;
2478 print_sockaddr(addr, sizeof(addr), &rm_addr);
2479 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2480 addr));
2483 if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2484 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2485 addr));
2486 return false;
2489 /* setup the connection */
2490 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2491 &rm_addr, 0, "IPC$", "IPC",
2492 "", /* username */
2493 "", /* domain */
2494 "", /* password */
2495 0, lp_client_signing());
2497 if ( !NT_STATUS_IS_OK( ret ) ) {
2498 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2499 remote_machine ));
2500 return false;
2503 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2504 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2505 cli_shutdown(the_cli);
2506 return false;
2510 * Ok - we have an anonymous connection to the IPC$ share.
2511 * Now start the NT Domain stuff :-).
2514 ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2515 if (!NT_STATUS_IS_OK(ret)) {
2516 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2517 remote_machine, nt_errstr(ret)));
2518 cli_shutdown(the_cli);
2519 return false;
2522 return true;
2525 /***************************************************************************
2526 Connect to the client.
2527 ****************************************************************************/
2529 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2530 uint32_t localprinter,
2531 enum winreg_Type type,
2532 struct policy_handle *handle,
2533 struct notify_back_channel **_chan,
2534 struct sockaddr_storage *client_ss,
2535 struct messaging_context *msg_ctx)
2537 WERROR result;
2538 NTSTATUS status;
2539 struct notify_back_channel *chan;
2541 for (chan = back_channels; chan; chan = chan->next) {
2542 if (memcmp(&chan->client_address, client_ss,
2543 sizeof(struct sockaddr_storage)) == 0) {
2544 break;
2549 * If it's the first connection, contact the client
2550 * and connect to the IPC$ share anonymously
2552 if (!chan) {
2553 fstring unix_printer;
2555 /* the +2 is to strip the leading 2 backslashs */
2556 fstrcpy(unix_printer, printer + 2);
2558 chan = talloc_zero(back_channels, struct notify_back_channel);
2559 if (!chan) {
2560 return false;
2562 chan->client_address = *client_ss;
2564 if (!spoolss_connect_to_client(&chan->cli_pipe, client_ss, unix_printer)) {
2565 TALLOC_FREE(chan);
2566 return false;
2568 chan->binding_handle = chan->cli_pipe->binding_handle;
2570 DLIST_ADD(back_channels, chan);
2572 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2573 receive_notify2_message_list);
2574 /* Tell the connections db we're now interested in printer
2575 * notify messages. */
2576 serverid_register_msg_flags(messaging_server_id(msg_ctx),
2577 true, FLAG_MSG_PRINT_NOTIFY);
2581 * Tell the specific printing tdb we want messages for this printer
2582 * by registering our PID.
2585 if (!print_notify_register_pid(snum)) {
2586 DEBUG(0, ("Failed to register our pid for printer %s\n",
2587 printer));
2590 status = dcerpc_spoolss_ReplyOpenPrinter(chan->binding_handle,
2591 talloc_tos(),
2592 printer,
2593 localprinter,
2594 type,
2596 NULL,
2597 handle,
2598 &result);
2599 if (!NT_STATUS_IS_OK(status)) {
2600 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2601 result = ntstatus_to_werror(status);
2602 } else if (!W_ERROR_IS_OK(result)) {
2603 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2606 chan->active_connections++;
2607 *_chan = chan;
2609 return (W_ERROR_IS_OK(result));
2612 /****************************************************************
2613 ****************************************************************/
2615 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2616 const struct spoolss_NotifyOption *r)
2618 struct spoolss_NotifyOption *option;
2619 uint32_t i,k;
2621 if (!r) {
2622 return NULL;
2625 option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2626 if (!option) {
2627 return NULL;
2630 *option = *r;
2632 if (!option->count) {
2633 return option;
2636 option->types = talloc_zero_array(option,
2637 struct spoolss_NotifyOptionType, option->count);
2638 if (!option->types) {
2639 talloc_free(option);
2640 return NULL;
2643 for (i=0; i < option->count; i++) {
2644 option->types[i] = r->types[i];
2646 if (option->types[i].count) {
2647 option->types[i].fields = talloc_zero_array(option,
2648 union spoolss_Field, option->types[i].count);
2649 if (!option->types[i].fields) {
2650 talloc_free(option);
2651 return NULL;
2653 for (k=0; k<option->types[i].count; k++) {
2654 option->types[i].fields[k] =
2655 r->types[i].fields[k];
2660 return option;
2663 /****************************************************************
2664 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2666 * before replying OK: status=0 a rpc call is made to the workstation
2667 * asking ReplyOpenPrinter
2669 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2670 * called from api_spoolss_rffpcnex
2671 ****************************************************************/
2673 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2674 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2676 int snum = -1;
2677 struct spoolss_NotifyOption *option = r->in.notify_options;
2678 struct sockaddr_storage client_ss;
2680 /* store the notify value in the printer struct */
2682 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2684 if (!Printer) {
2685 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2686 "Invalid handle (%s:%u:%u).\n",
2687 OUR_HANDLE(r->in.handle)));
2688 return WERR_BADFID;
2691 Printer->notify.flags = r->in.flags;
2692 Printer->notify.options = r->in.options;
2693 Printer->notify.printerlocal = r->in.printer_local;
2694 Printer->notify.msg_ctx = p->msg_ctx;
2696 TALLOC_FREE(Printer->notify.option);
2697 Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2699 fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2701 /* Connect to the client machine and send a ReplyOpenPrinter */
2703 if ( Printer->printer_type == SPLHND_SERVER)
2704 snum = -1;
2705 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2706 !get_printer_snum(p, r->in.handle, &snum, NULL) )
2707 return WERR_BADFID;
2709 DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2710 "client_address is %s\n", p->client_id->addr));
2712 if (!lp_print_notify_backchannel(snum)) {
2713 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2714 "backchannel disabled\n"));
2715 return WERR_SERVER_UNAVAILABLE;
2718 if (!interpret_string_addr(&client_ss, p->client_id->addr,
2719 AI_NUMERICHOST)) {
2720 return WERR_SERVER_UNAVAILABLE;
2723 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2724 Printer->notify.printerlocal, REG_SZ,
2725 &Printer->notify.cli_hnd,
2726 &Printer->notify.cli_chan,
2727 &client_ss, p->msg_ctx)) {
2728 return WERR_SERVER_UNAVAILABLE;
2731 return WERR_OK;
2734 /*******************************************************************
2735 * fill a notify_info_data with the servername
2736 ********************************************************************/
2738 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2739 int snum,
2740 struct spoolss_Notify *data,
2741 print_queue_struct *queue,
2742 struct spoolss_PrinterInfo2 *pinfo2,
2743 TALLOC_CTX *mem_ctx)
2745 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2748 /*******************************************************************
2749 * fill a notify_info_data with the printername (not including the servername).
2750 ********************************************************************/
2752 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2753 int snum,
2754 struct spoolss_Notify *data,
2755 print_queue_struct *queue,
2756 struct spoolss_PrinterInfo2 *pinfo2,
2757 TALLOC_CTX *mem_ctx)
2759 /* the notify name should not contain the \\server\ part */
2760 const char *p = strrchr(pinfo2->printername, '\\');
2762 if (!p) {
2763 p = pinfo2->printername;
2764 } else {
2765 p++;
2768 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2771 /*******************************************************************
2772 * fill a notify_info_data with the servicename
2773 ********************************************************************/
2775 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2776 int snum,
2777 struct spoolss_Notify *data,
2778 print_queue_struct *queue,
2779 struct spoolss_PrinterInfo2 *pinfo2,
2780 TALLOC_CTX *mem_ctx)
2782 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2785 /*******************************************************************
2786 * fill a notify_info_data with the port name
2787 ********************************************************************/
2789 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2790 int snum,
2791 struct spoolss_Notify *data,
2792 print_queue_struct *queue,
2793 struct spoolss_PrinterInfo2 *pinfo2,
2794 TALLOC_CTX *mem_ctx)
2796 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2799 /*******************************************************************
2800 * fill a notify_info_data with the printername
2801 * but it doesn't exist, have to see what to do
2802 ********************************************************************/
2804 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2805 int snum,
2806 struct spoolss_Notify *data,
2807 print_queue_struct *queue,
2808 struct spoolss_PrinterInfo2 *pinfo2,
2809 TALLOC_CTX *mem_ctx)
2811 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2814 /*******************************************************************
2815 * fill a notify_info_data with the comment
2816 ********************************************************************/
2818 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2819 int snum,
2820 struct spoolss_Notify *data,
2821 print_queue_struct *queue,
2822 struct spoolss_PrinterInfo2 *pinfo2,
2823 TALLOC_CTX *mem_ctx)
2825 const char *p;
2827 if (*pinfo2->comment == '\0') {
2828 p = lp_comment(snum);
2829 } else {
2830 p = pinfo2->comment;
2833 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2836 /*******************************************************************
2837 * fill a notify_info_data with the comment
2838 * location = "Room 1, floor 2, building 3"
2839 ********************************************************************/
2841 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2842 int snum,
2843 struct spoolss_Notify *data,
2844 print_queue_struct *queue,
2845 struct spoolss_PrinterInfo2 *pinfo2,
2846 TALLOC_CTX *mem_ctx)
2848 const char *loc = pinfo2->location;
2849 NTSTATUS status;
2851 status = printer_list_get_printer(mem_ctx,
2852 pinfo2->sharename,
2853 NULL,
2854 &loc,
2855 NULL);
2856 if (NT_STATUS_IS_OK(status)) {
2857 if (loc == NULL) {
2858 loc = pinfo2->location;
2862 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, loc);
2865 /*******************************************************************
2866 * fill a notify_info_data with the device mode
2867 * jfm:xxxx don't to it for know but that's a real problem !!!
2868 ********************************************************************/
2870 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2871 int snum,
2872 struct spoolss_Notify *data,
2873 print_queue_struct *queue,
2874 struct spoolss_PrinterInfo2 *pinfo2,
2875 TALLOC_CTX *mem_ctx)
2877 /* for a dummy implementation we have to zero the fields */
2878 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2881 /*******************************************************************
2882 * fill a notify_info_data with the separator file name
2883 ********************************************************************/
2885 static void spoolss_notify_sepfile(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 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2895 /*******************************************************************
2896 * fill a notify_info_data with the print processor
2897 * jfm:xxxx return always winprint to indicate we don't do anything to it
2898 ********************************************************************/
2900 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2901 int snum,
2902 struct spoolss_Notify *data,
2903 print_queue_struct *queue,
2904 struct spoolss_PrinterInfo2 *pinfo2,
2905 TALLOC_CTX *mem_ctx)
2907 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2910 /*******************************************************************
2911 * fill a notify_info_data with the print processor options
2912 * jfm:xxxx send an empty string
2913 ********************************************************************/
2915 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2916 int snum,
2917 struct spoolss_Notify *data,
2918 print_queue_struct *queue,
2919 struct spoolss_PrinterInfo2 *pinfo2,
2920 TALLOC_CTX *mem_ctx)
2922 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2925 /*******************************************************************
2926 * fill a notify_info_data with the data type
2927 * jfm:xxxx always send RAW as data type
2928 ********************************************************************/
2930 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2931 int snum,
2932 struct spoolss_Notify *data,
2933 print_queue_struct *queue,
2934 struct spoolss_PrinterInfo2 *pinfo2,
2935 TALLOC_CTX *mem_ctx)
2937 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2940 /*******************************************************************
2941 * fill a notify_info_data with the security descriptor
2942 * jfm:xxxx send an null pointer to say no security desc
2943 * have to implement security before !
2944 ********************************************************************/
2946 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2947 int snum,
2948 struct spoolss_Notify *data,
2949 print_queue_struct *queue,
2950 struct spoolss_PrinterInfo2 *pinfo2,
2951 TALLOC_CTX *mem_ctx)
2953 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
2956 /*******************************************************************
2957 * fill a notify_info_data with the attributes
2958 * jfm:xxxx a samba printer is always shared
2959 ********************************************************************/
2961 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2962 int snum,
2963 struct spoolss_Notify *data,
2964 print_queue_struct *queue,
2965 struct spoolss_PrinterInfo2 *pinfo2,
2966 TALLOC_CTX *mem_ctx)
2968 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2971 /*******************************************************************
2972 * fill a notify_info_data with the priority
2973 ********************************************************************/
2975 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
2976 int snum,
2977 struct spoolss_Notify *data,
2978 print_queue_struct *queue,
2979 struct spoolss_PrinterInfo2 *pinfo2,
2980 TALLOC_CTX *mem_ctx)
2982 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
2985 /*******************************************************************
2986 * fill a notify_info_data with the default priority
2987 ********************************************************************/
2989 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
2990 int snum,
2991 struct spoolss_Notify *data,
2992 print_queue_struct *queue,
2993 struct spoolss_PrinterInfo2 *pinfo2,
2994 TALLOC_CTX *mem_ctx)
2996 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
2999 /*******************************************************************
3000 * fill a notify_info_data with the start time
3001 ********************************************************************/
3003 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
3004 int snum,
3005 struct spoolss_Notify *data,
3006 print_queue_struct *queue,
3007 struct spoolss_PrinterInfo2 *pinfo2,
3008 TALLOC_CTX *mem_ctx)
3010 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3013 /*******************************************************************
3014 * fill a notify_info_data with the until time
3015 ********************************************************************/
3017 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3018 int snum,
3019 struct spoolss_Notify *data,
3020 print_queue_struct *queue,
3021 struct spoolss_PrinterInfo2 *pinfo2,
3022 TALLOC_CTX *mem_ctx)
3024 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3027 /*******************************************************************
3028 * fill a notify_info_data with the status
3029 ********************************************************************/
3031 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3032 int snum,
3033 struct spoolss_Notify *data,
3034 print_queue_struct *queue,
3035 struct spoolss_PrinterInfo2 *pinfo2,
3036 TALLOC_CTX *mem_ctx)
3038 print_status_struct status;
3040 print_queue_length(msg_ctx, snum, &status);
3041 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3044 /*******************************************************************
3045 * fill a notify_info_data with the number of jobs queued
3046 ********************************************************************/
3048 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3049 int snum,
3050 struct spoolss_Notify *data,
3051 print_queue_struct *queue,
3052 struct spoolss_PrinterInfo2 *pinfo2,
3053 TALLOC_CTX *mem_ctx)
3055 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3056 data, print_queue_length(msg_ctx, snum, NULL));
3059 /*******************************************************************
3060 * fill a notify_info_data with the average ppm
3061 ********************************************************************/
3063 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3064 int snum,
3065 struct spoolss_Notify *data,
3066 print_queue_struct *queue,
3067 struct spoolss_PrinterInfo2 *pinfo2,
3068 TALLOC_CTX *mem_ctx)
3070 /* always respond 8 pages per minutes */
3071 /* a little hard ! */
3072 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3075 /*******************************************************************
3076 * fill a notify_info_data with username
3077 ********************************************************************/
3079 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3080 int snum,
3081 struct spoolss_Notify *data,
3082 print_queue_struct *queue,
3083 struct spoolss_PrinterInfo2 *pinfo2,
3084 TALLOC_CTX *mem_ctx)
3086 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3089 /*******************************************************************
3090 * fill a notify_info_data with job status
3091 ********************************************************************/
3093 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3094 int snum,
3095 struct spoolss_Notify *data,
3096 print_queue_struct *queue,
3097 struct spoolss_PrinterInfo2 *pinfo2,
3098 TALLOC_CTX *mem_ctx)
3100 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3103 /*******************************************************************
3104 * fill a notify_info_data with job name
3105 ********************************************************************/
3107 static void spoolss_notify_job_name(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 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3117 /*******************************************************************
3118 * fill a notify_info_data with job status
3119 ********************************************************************/
3121 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3122 int snum,
3123 struct spoolss_Notify *data,
3124 print_queue_struct *queue,
3125 struct spoolss_PrinterInfo2 *pinfo2,
3126 TALLOC_CTX *mem_ctx)
3129 * Now we're returning job status codes we just return a "" here. JRA.
3132 const char *p = "";
3134 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3135 p = "unknown";
3137 switch (queue->status) {
3138 case LPQ_QUEUED:
3139 p = "Queued";
3140 break;
3141 case LPQ_PAUSED:
3142 p = ""; /* NT provides the paused string */
3143 break;
3144 case LPQ_SPOOLING:
3145 p = "Spooling";
3146 break;
3147 case LPQ_PRINTING:
3148 p = "Printing";
3149 break;
3151 #endif /* NO LONGER NEEDED. */
3153 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3156 /*******************************************************************
3157 * fill a notify_info_data with job time
3158 ********************************************************************/
3160 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3161 int snum,
3162 struct spoolss_Notify *data,
3163 print_queue_struct *queue,
3164 struct spoolss_PrinterInfo2 *pinfo2,
3165 TALLOC_CTX *mem_ctx)
3167 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3170 /*******************************************************************
3171 * fill a notify_info_data with job size
3172 ********************************************************************/
3174 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3175 int snum,
3176 struct spoolss_Notify *data,
3177 print_queue_struct *queue,
3178 struct spoolss_PrinterInfo2 *pinfo2,
3179 TALLOC_CTX *mem_ctx)
3181 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3184 /*******************************************************************
3185 * fill a notify_info_data with page info
3186 ********************************************************************/
3187 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3188 int snum,
3189 struct spoolss_Notify *data,
3190 print_queue_struct *queue,
3191 struct spoolss_PrinterInfo2 *pinfo2,
3192 TALLOC_CTX *mem_ctx)
3194 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3197 /*******************************************************************
3198 * fill a notify_info_data with pages printed info.
3199 ********************************************************************/
3200 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3201 int snum,
3202 struct spoolss_Notify *data,
3203 print_queue_struct *queue,
3204 struct spoolss_PrinterInfo2 *pinfo2,
3205 TALLOC_CTX *mem_ctx)
3207 /* Add code when back-end tracks this */
3208 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3211 /*******************************************************************
3212 Fill a notify_info_data with job position.
3213 ********************************************************************/
3215 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3216 int snum,
3217 struct spoolss_Notify *data,
3218 print_queue_struct *queue,
3219 struct spoolss_PrinterInfo2 *pinfo2,
3220 TALLOC_CTX *mem_ctx)
3222 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3225 /*******************************************************************
3226 Fill a notify_info_data with submitted time.
3227 ********************************************************************/
3229 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3230 int snum,
3231 struct spoolss_Notify *data,
3232 print_queue_struct *queue,
3233 struct spoolss_PrinterInfo2 *pinfo2,
3234 TALLOC_CTX *mem_ctx)
3236 data->data.string.string = NULL;
3237 data->data.string.size = 0;
3239 init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3240 &data->data.string.string,
3241 &data->data.string.size);
3245 struct s_notify_info_data_table
3247 enum spoolss_NotifyType type;
3248 uint16_t field;
3249 const char *name;
3250 enum spoolss_NotifyTable variable_type;
3251 void (*fn) (struct messaging_context *msg_ctx,
3252 int snum, struct spoolss_Notify *data,
3253 print_queue_struct *queue,
3254 struct spoolss_PrinterInfo2 *pinfo2,
3255 TALLOC_CTX *mem_ctx);
3258 /* A table describing the various print notification constants and
3259 whether the notification data is a pointer to a variable sized
3260 buffer, a one value uint32_t or a two value uint32_t. */
3262 static const struct s_notify_info_data_table notify_info_data_table[] =
3264 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3265 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3266 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
3267 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3268 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3269 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
3270 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
3271 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3272 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
3273 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3274 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3275 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3276 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
3277 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
3278 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3279 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
3280 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3281 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3282 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
3283 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
3284 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
3285 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
3286 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
3287 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3288 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
3289 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3290 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINTER_NAME, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3291 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_MACHINE_NAME, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3292 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PORT_NAME, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3293 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_USER_NAME, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3294 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_NOTIFY_NAME, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3295 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DATATYPE, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3296 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINT_PROCESSOR, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3297 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PARAMETERS, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3298 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DRIVER_NAME, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3299 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DEVMODE, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3300 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
3301 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS_STRING, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
3302 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
3303 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DOCUMENT, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
3304 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRIORITY, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3305 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_POSITION, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
3306 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SUBMITTED, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
3307 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_START_TIME, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3308 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_UNTIL_TIME, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3309 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TIME, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
3310 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_PAGES, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
3311 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PAGES_PRINTED, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
3312 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_BYTES, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
3315 /*******************************************************************
3316 Return the variable_type of info_data structure.
3317 ********************************************************************/
3319 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3320 uint16_t field)
3322 int i=0;
3324 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3325 if ( (notify_info_data_table[i].type == type) &&
3326 (notify_info_data_table[i].field == field) ) {
3327 return notify_info_data_table[i].variable_type;
3331 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3333 return (enum spoolss_NotifyTable) 0;
3336 /****************************************************************************
3337 ****************************************************************************/
3339 static bool search_notify(enum spoolss_NotifyType type,
3340 uint16_t field,
3341 int *value)
3343 int i;
3345 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3346 if (notify_info_data_table[i].type == type &&
3347 notify_info_data_table[i].field == field &&
3348 notify_info_data_table[i].fn != NULL) {
3349 *value = i;
3350 return true;
3354 return false;
3357 /****************************************************************************
3358 ****************************************************************************/
3360 static void construct_info_data(struct spoolss_Notify *info_data,
3361 enum spoolss_NotifyType type,
3362 uint16_t field, int id)
3364 info_data->type = type;
3365 info_data->field.field = field;
3366 info_data->variable_type = variable_type_of_notify_info_data(type, field);
3367 info_data->job_id = id;
3370 /*******************************************************************
3372 * fill a notify_info struct with info asked
3374 ********************************************************************/
3376 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3377 struct printer_handle *print_hnd,
3378 struct spoolss_NotifyInfo *info,
3379 struct spoolss_PrinterInfo2 *pinfo2,
3380 int snum,
3381 const struct spoolss_NotifyOptionType *option_type,
3382 uint32_t id,
3383 TALLOC_CTX *mem_ctx)
3385 int field_num,j;
3386 enum spoolss_NotifyType type;
3387 uint16_t field;
3389 struct spoolss_Notify *current_data;
3391 type = option_type->type;
3393 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3394 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3395 option_type->count, lp_servicename(snum)));
3397 for(field_num=0; field_num < option_type->count; field_num++) {
3398 field = option_type->fields[field_num].field;
3400 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3402 if (!search_notify(type, field, &j) )
3403 continue;
3405 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3406 struct spoolss_Notify,
3407 info->count + 1);
3408 if (info->notifies == NULL) {
3409 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3410 return false;
3413 current_data = &info->notifies[info->count];
3415 construct_info_data(current_data, type, field, id);
3417 DEBUG(10, ("construct_notify_printer_info: "
3418 "calling [%s] snum=%d printername=[%s])\n",
3419 notify_info_data_table[j].name, snum,
3420 pinfo2->printername));
3422 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3423 NULL, pinfo2, mem_ctx);
3425 info->count++;
3428 return true;
3431 /*******************************************************************
3433 * fill a notify_info struct with info asked
3435 ********************************************************************/
3437 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3438 print_queue_struct *queue,
3439 struct spoolss_NotifyInfo *info,
3440 struct spoolss_PrinterInfo2 *pinfo2,
3441 int snum,
3442 const struct spoolss_NotifyOptionType *option_type,
3443 uint32_t id,
3444 TALLOC_CTX *mem_ctx)
3446 int field_num,j;
3447 enum spoolss_NotifyType type;
3448 uint16_t field;
3449 struct spoolss_Notify *current_data;
3451 DEBUG(4,("construct_notify_jobs_info\n"));
3453 type = option_type->type;
3455 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3456 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3457 option_type->count));
3459 for(field_num=0; field_num<option_type->count; field_num++) {
3460 field = option_type->fields[field_num].field;
3462 if (!search_notify(type, field, &j) )
3463 continue;
3465 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3466 struct spoolss_Notify,
3467 info->count + 1);
3468 if (info->notifies == NULL) {
3469 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3470 return false;
3473 current_data=&(info->notifies[info->count]);
3475 construct_info_data(current_data, type, field, id);
3476 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3477 queue, pinfo2, mem_ctx);
3478 info->count++;
3481 return true;
3485 * JFM: The enumeration is not that simple, it's even non obvious.
3487 * let's take an example: I want to monitor the PRINTER SERVER for
3488 * the printer's name and the number of jobs currently queued.
3489 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3490 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3492 * I have 3 printers on the back of my server.
3494 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3495 * structures.
3496 * Number Data Id
3497 * 1 printer 1 name 1
3498 * 2 printer 1 cjob 1
3499 * 3 printer 2 name 2
3500 * 4 printer 2 cjob 2
3501 * 5 printer 3 name 3
3502 * 6 printer 3 name 3
3504 * that's the print server case, the printer case is even worse.
3507 /*******************************************************************
3509 * enumerate all printers on the printserver
3510 * fill a notify_info struct with info asked
3512 ********************************************************************/
3514 static WERROR printserver_notify_info(struct pipes_struct *p,
3515 struct policy_handle *hnd,
3516 struct spoolss_NotifyInfo *info,
3517 TALLOC_CTX *mem_ctx)
3519 int snum;
3520 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3521 int n_services=lp_numservices();
3522 int i;
3523 struct spoolss_NotifyOption *option;
3524 struct spoolss_NotifyOptionType option_type;
3525 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3526 WERROR result;
3528 DEBUG(4,("printserver_notify_info\n"));
3530 if (!Printer)
3531 return WERR_BADFID;
3533 option = Printer->notify.option;
3535 info->version = 2;
3536 info->notifies = NULL;
3537 info->count = 0;
3539 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3540 sending a ffpcn() request first */
3542 if ( !option )
3543 return WERR_BADFID;
3545 for (i=0; i<option->count; i++) {
3546 option_type = option->types[i];
3548 if (option_type.type != PRINTER_NOTIFY_TYPE)
3549 continue;
3551 for (snum = 0; snum < n_services; snum++) {
3552 if (!lp_browseable(snum) ||
3553 !lp_snum_ok(snum) ||
3554 !lp_print_ok(snum)) {
3555 continue; /* skip */
3558 /* Maybe we should use the SYSTEM session_info here... */
3559 result = winreg_get_printer_internal(mem_ctx,
3560 get_session_info_system(),
3561 p->msg_ctx,
3562 lp_servicename(snum),
3563 &pinfo2);
3564 if (!W_ERROR_IS_OK(result)) {
3565 DEBUG(4, ("printserver_notify_info: "
3566 "Failed to get printer [%s]\n",
3567 lp_servicename(snum)));
3568 continue;
3572 construct_notify_printer_info(p->msg_ctx,
3573 Printer, info,
3574 pinfo2, snum,
3575 &option_type, snum,
3576 mem_ctx);
3578 TALLOC_FREE(pinfo2);
3582 #if 0
3584 * Debugging information, don't delete.
3587 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3588 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3589 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3591 for (i=0; i<info->count; i++) {
3592 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3593 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3594 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3596 #endif
3598 return WERR_OK;
3601 /*******************************************************************
3603 * fill a notify_info struct with info asked
3605 ********************************************************************/
3607 static WERROR printer_notify_info(struct pipes_struct *p,
3608 struct policy_handle *hnd,
3609 struct spoolss_NotifyInfo *info,
3610 TALLOC_CTX *mem_ctx)
3612 int snum;
3613 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3614 int i;
3615 uint32_t id;
3616 struct spoolss_NotifyOption *option;
3617 struct spoolss_NotifyOptionType option_type;
3618 int count,j;
3619 print_queue_struct *queue=NULL;
3620 print_status_struct status;
3621 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3622 WERROR result;
3624 DEBUG(4,("printer_notify_info\n"));
3626 if (!Printer)
3627 return WERR_BADFID;
3629 option = Printer->notify.option;
3630 id = 0x0;
3632 info->version = 2;
3633 info->notifies = NULL;
3634 info->count = 0;
3636 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3637 sending a ffpcn() request first */
3639 if ( !option )
3640 return WERR_BADFID;
3642 if (!get_printer_snum(p, hnd, &snum, NULL)) {
3643 return WERR_BADFID;
3646 /* Maybe we should use the SYSTEM session_info here... */
3647 result = winreg_get_printer_internal(mem_ctx,
3648 get_session_info_system(),
3649 p->msg_ctx,
3650 lp_servicename(snum), &pinfo2);
3651 if (!W_ERROR_IS_OK(result)) {
3652 return WERR_BADFID;
3656 * When sending a PRINTER_NOTIFY_FIELD_SERVER_NAME we should send the
3657 * correct servername.
3659 pinfo2->servername = talloc_strdup(pinfo2, Printer->servername);
3660 if (pinfo2->servername == NULL) {
3661 return WERR_NOMEM;
3664 for (i=0; i<option->count; i++) {
3665 option_type = option->types[i];
3667 switch (option_type.type) {
3668 case PRINTER_NOTIFY_TYPE:
3669 if (construct_notify_printer_info(p->msg_ctx,
3670 Printer, info,
3671 pinfo2, snum,
3672 &option_type, id,
3673 mem_ctx)) {
3674 id--;
3676 break;
3678 case JOB_NOTIFY_TYPE:
3680 count = print_queue_status(p->msg_ctx, snum, &queue,
3681 &status);
3683 for (j=0; j<count; j++) {
3684 construct_notify_jobs_info(p->msg_ctx,
3685 &queue[j], info,
3686 pinfo2, snum,
3687 &option_type,
3688 queue[j].job,
3689 mem_ctx);
3692 SAFE_FREE(queue);
3693 break;
3698 * Debugging information, don't delete.
3701 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3702 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3703 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3705 for (i=0; i<info->count; i++) {
3706 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3707 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3708 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3712 talloc_free(pinfo2);
3713 return WERR_OK;
3716 /****************************************************************
3717 _spoolss_RouterRefreshPrinterChangeNotify
3718 ****************************************************************/
3720 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3721 struct spoolss_RouterRefreshPrinterChangeNotify *r)
3723 struct spoolss_NotifyInfo *info;
3725 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3726 WERROR result = WERR_BADFID;
3728 /* we always have a spoolss_NotifyInfo struct */
3729 info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3730 if (!info) {
3731 result = WERR_NOMEM;
3732 goto done;
3735 *r->out.info = info;
3737 if (!Printer) {
3738 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3739 "Invalid handle (%s:%u:%u).\n",
3740 OUR_HANDLE(r->in.handle)));
3741 goto done;
3744 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3747 * We are now using the change value, and
3748 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3749 * I don't have a global notification system, I'm sending back all the
3750 * information even when _NOTHING_ has changed.
3753 /* We need to keep track of the change value to send back in
3754 RRPCN replies otherwise our updates are ignored. */
3756 Printer->notify.fnpcn = true;
3758 if (Printer->notify.cli_chan != NULL &&
3759 Printer->notify.cli_chan->active_connections > 0) {
3760 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3761 "Saving change value in request [%x]\n",
3762 r->in.change_low));
3763 Printer->notify.change = r->in.change_low;
3766 /* just ignore the spoolss_NotifyOption */
3768 switch (Printer->printer_type) {
3769 case SPLHND_SERVER:
3770 result = printserver_notify_info(p, r->in.handle,
3771 info, p->mem_ctx);
3772 break;
3774 case SPLHND_PRINTER:
3775 result = printer_notify_info(p, r->in.handle,
3776 info, p->mem_ctx);
3777 break;
3780 Printer->notify.fnpcn = false;
3782 done:
3783 return result;
3786 /********************************************************************
3787 ********************************************************************/
3789 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3790 const char *servername,
3791 const char *printername,
3792 const char **printername_p)
3794 /* FIXME: add lp_force_printername() */
3796 if (servername == NULL) {
3797 *printername_p = talloc_strdup(mem_ctx, printername);
3798 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3799 return WERR_OK;
3802 if (servername[0] == '\\' && servername[1] == '\\') {
3803 servername += 2;
3806 *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3807 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3809 return WERR_OK;
3812 /********************************************************************
3813 ********************************************************************/
3815 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3816 const char *printername)
3818 if (dm == NULL) {
3819 return;
3822 dm->devicename = talloc_strndup(dm, printername,
3823 MIN(strlen(printername), 31));
3826 /********************************************************************
3827 * construct_printer_info_0
3828 * fill a printer_info_0 struct
3829 ********************************************************************/
3831 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3832 const struct auth_serversupplied_info *session_info,
3833 struct messaging_context *msg_ctx,
3834 struct spoolss_PrinterInfo2 *info2,
3835 const char *servername,
3836 struct spoolss_PrinterInfo0 *r,
3837 int snum)
3839 int count;
3840 struct printer_session_counter *session_counter;
3841 struct timeval setuptime;
3842 print_status_struct status;
3843 WERROR result;
3845 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3846 if (!W_ERROR_IS_OK(result)) {
3847 return result;
3850 if (servername) {
3851 r->servername = talloc_strdup(mem_ctx, servername);
3852 W_ERROR_HAVE_NO_MEMORY(r->servername);
3853 } else {
3854 r->servername = NULL;
3857 count = print_queue_length(msg_ctx, snum, &status);
3859 /* check if we already have a counter for this printer */
3860 for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3861 if (session_counter->snum == snum)
3862 break;
3865 /* it's the first time, add it to the list */
3866 if (session_counter == NULL) {
3867 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3868 W_ERROR_HAVE_NO_MEMORY(session_counter);
3869 session_counter->snum = snum;
3870 session_counter->counter = 0;
3871 DLIST_ADD(counter_list, session_counter);
3874 /* increment it */
3875 session_counter->counter++;
3877 r->cjobs = count;
3878 r->total_jobs = 0;
3879 r->total_bytes = 0;
3881 get_startup_time(&setuptime);
3882 init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3884 /* JFM:
3885 * the global_counter should be stored in a TDB as it's common to all the clients
3886 * and should be zeroed on samba startup
3888 r->global_counter = session_counter->counter;
3889 r->total_pages = 0;
3890 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3891 SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3892 SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3893 r->free_build = SPOOLSS_RELEASE_BUILD;
3894 r->spooling = 0;
3895 r->max_spooling = 0;
3896 r->session_counter = session_counter->counter;
3897 r->num_error_out_of_paper = 0x0;
3898 r->num_error_not_ready = 0x0; /* number of print failure */
3899 r->job_error = 0x0;
3900 r->number_of_processors = 0x1;
3901 r->processor_type = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3902 r->high_part_total_bytes = 0x0;
3904 /* ChangeID in milliseconds*/
3905 winreg_printer_get_changeid_internal(mem_ctx, session_info, msg_ctx,
3906 info2->sharename, &r->change_id);
3908 r->last_error = WERR_OK;
3909 r->status = nt_printq_status(status.status);
3910 r->enumerate_network_printers = 0x0;
3911 r->c_setprinter = 0x0;
3912 r->processor_architecture = PROCESSOR_ARCHITECTURE_INTEL;
3913 r->processor_level = 0x6; /* 6 ???*/
3914 r->ref_ic = 0;
3915 r->reserved2 = 0;
3916 r->reserved3 = 0;
3918 return WERR_OK;
3922 /********************************************************************
3923 * construct_printer_info1
3924 * fill a spoolss_PrinterInfo1 struct
3925 ********************************************************************/
3927 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3928 const struct spoolss_PrinterInfo2 *info2,
3929 uint32_t flags,
3930 const char *servername,
3931 struct spoolss_PrinterInfo1 *r,
3932 int snum)
3934 WERROR result;
3936 r->flags = flags;
3938 if (info2->comment == NULL || info2->comment[0] == '\0') {
3939 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
3940 } else {
3941 r->comment = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3943 W_ERROR_HAVE_NO_MEMORY(r->comment);
3945 result = create_printername(mem_ctx, servername, info2->printername, &r->name);
3946 if (!W_ERROR_IS_OK(result)) {
3947 return result;
3950 r->description = talloc_asprintf(mem_ctx, "%s,%s,%s",
3951 r->name,
3952 info2->drivername,
3953 r->comment);
3954 W_ERROR_HAVE_NO_MEMORY(r->description);
3956 return WERR_OK;
3959 /********************************************************************
3960 * construct_printer_info2
3961 * fill a spoolss_PrinterInfo2 struct
3962 ********************************************************************/
3964 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3965 struct messaging_context *msg_ctx,
3966 const struct spoolss_PrinterInfo2 *info2,
3967 const char *servername,
3968 struct spoolss_PrinterInfo2 *r,
3969 int snum)
3971 int count;
3972 print_status_struct status;
3973 WERROR result;
3975 count = print_queue_length(msg_ctx, snum, &status);
3977 if (servername) {
3978 r->servername = talloc_strdup(mem_ctx, servername);
3979 W_ERROR_HAVE_NO_MEMORY(r->servername);
3980 } else {
3981 r->servername = NULL;
3984 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3985 if (!W_ERROR_IS_OK(result)) {
3986 return result;
3989 r->sharename = talloc_strdup(mem_ctx, lp_servicename(snum));
3990 W_ERROR_HAVE_NO_MEMORY(r->sharename);
3991 r->portname = talloc_strdup(mem_ctx, info2->portname);
3992 W_ERROR_HAVE_NO_MEMORY(r->portname);
3993 r->drivername = talloc_strdup(mem_ctx, info2->drivername);
3994 W_ERROR_HAVE_NO_MEMORY(r->drivername);
3996 if (info2->comment[0] == '\0') {
3997 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
3998 } else {
3999 r->comment = talloc_strdup(mem_ctx, info2->comment);
4001 W_ERROR_HAVE_NO_MEMORY(r->comment);
4003 r->location = talloc_strdup(mem_ctx, info2->location);
4004 if (info2->location[0] == '\0') {
4005 const char *loc = NULL;
4006 NTSTATUS nt_status;
4008 nt_status = printer_list_get_printer(mem_ctx,
4009 info2->sharename,
4010 NULL,
4011 &loc,
4012 NULL);
4013 if (NT_STATUS_IS_OK(nt_status)) {
4014 if (loc != NULL) {
4015 r->location = talloc_strdup(mem_ctx, loc);
4019 W_ERROR_HAVE_NO_MEMORY(r->location);
4021 r->sepfile = talloc_strdup(mem_ctx, info2->sepfile);
4022 W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4023 r->printprocessor = talloc_strdup(mem_ctx, info2->printprocessor);
4024 W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4025 r->datatype = talloc_strdup(mem_ctx, info2->datatype);
4026 W_ERROR_HAVE_NO_MEMORY(r->datatype);
4027 r->parameters = talloc_strdup(mem_ctx, info2->parameters);
4028 W_ERROR_HAVE_NO_MEMORY(r->parameters);
4030 r->attributes = info2->attributes;
4032 r->priority = info2->priority;
4033 r->defaultpriority = info2->defaultpriority;
4034 r->starttime = info2->starttime;
4035 r->untiltime = info2->untiltime;
4036 r->status = nt_printq_status(status.status);
4037 r->cjobs = count;
4038 r->averageppm = info2->averageppm;
4040 copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4041 if (!r->devmode) {
4042 DEBUG(8,("Returning NULL Devicemode!\n"));
4045 compose_devicemode_devicename(r->devmode, r->printername);
4047 r->secdesc = NULL;
4049 if (info2->secdesc != NULL) {
4050 /* don't use talloc_steal() here unless you do a deep steal of all
4051 the SEC_DESC members */
4053 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4056 return WERR_OK;
4059 /********************************************************************
4060 * construct_printer_info3
4061 * fill a spoolss_PrinterInfo3 struct
4062 ********************************************************************/
4064 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4065 const struct spoolss_PrinterInfo2 *info2,
4066 const char *servername,
4067 struct spoolss_PrinterInfo3 *r,
4068 int snum)
4070 /* These are the components of the SD we are returning. */
4072 if (info2->secdesc != NULL) {
4073 /* don't use talloc_steal() here unless you do a deep steal of all
4074 the SEC_DESC members */
4076 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4077 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
4080 return WERR_OK;
4083 /********************************************************************
4084 * construct_printer_info4
4085 * fill a spoolss_PrinterInfo4 struct
4086 ********************************************************************/
4088 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4089 const struct spoolss_PrinterInfo2 *info2,
4090 const char *servername,
4091 struct spoolss_PrinterInfo4 *r,
4092 int snum)
4094 WERROR result;
4096 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4097 if (!W_ERROR_IS_OK(result)) {
4098 return result;
4101 if (servername) {
4102 r->servername = talloc_strdup(mem_ctx, servername);
4103 W_ERROR_HAVE_NO_MEMORY(r->servername);
4104 } else {
4105 r->servername = NULL;
4108 r->attributes = info2->attributes;
4110 return WERR_OK;
4113 /********************************************************************
4114 * construct_printer_info5
4115 * fill a spoolss_PrinterInfo5 struct
4116 ********************************************************************/
4118 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4119 const struct spoolss_PrinterInfo2 *info2,
4120 const char *servername,
4121 struct spoolss_PrinterInfo5 *r,
4122 int snum)
4124 WERROR result;
4126 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4127 if (!W_ERROR_IS_OK(result)) {
4128 return result;
4131 r->portname = talloc_strdup(mem_ctx, info2->portname);
4132 W_ERROR_HAVE_NO_MEMORY(r->portname);
4134 r->attributes = info2->attributes;
4136 /* these two are not used by NT+ according to MSDN */
4137 r->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4138 r->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4140 return WERR_OK;
4143 /********************************************************************
4144 * construct_printer_info_6
4145 * fill a spoolss_PrinterInfo6 struct
4146 ********************************************************************/
4148 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4149 struct messaging_context *msg_ctx,
4150 const struct spoolss_PrinterInfo2 *info2,
4151 const char *servername,
4152 struct spoolss_PrinterInfo6 *r,
4153 int snum)
4155 int count;
4156 print_status_struct status;
4158 count = print_queue_length(msg_ctx, snum, &status);
4160 r->status = nt_printq_status(status.status);
4162 return WERR_OK;
4165 /********************************************************************
4166 * construct_printer_info7
4167 * fill a spoolss_PrinterInfo7 struct
4168 ********************************************************************/
4170 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4171 struct messaging_context *msg_ctx,
4172 const char *servername,
4173 struct spoolss_PrinterInfo7 *r,
4174 int snum)
4176 struct auth_serversupplied_info *session_info;
4177 struct GUID guid;
4178 NTSTATUS status;
4180 status = make_session_info_system(mem_ctx, &session_info);
4181 if (!NT_STATUS_IS_OK(status)) {
4182 DEBUG(0, ("construct_printer_info7: "
4183 "Could not create system session_info\n"));
4184 return WERR_NOMEM;
4187 if (is_printer_published(mem_ctx, session_info, msg_ctx,
4188 servername,
4189 lp_servicename(snum), &guid, NULL)) {
4190 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4191 r->action = DSPRINT_PUBLISH;
4192 } else {
4193 r->guid = talloc_strdup(mem_ctx, "");
4194 r->action = DSPRINT_UNPUBLISH;
4196 W_ERROR_HAVE_NO_MEMORY(r->guid);
4198 TALLOC_FREE(session_info);
4199 return WERR_OK;
4202 /********************************************************************
4203 * construct_printer_info8
4204 * fill a spoolss_PrinterInfo8 struct
4205 ********************************************************************/
4207 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4208 const struct spoolss_PrinterInfo2 *info2,
4209 const char *servername,
4210 struct spoolss_DeviceModeInfo *r,
4211 int snum)
4213 WERROR result;
4214 const char *printername;
4216 result = create_printername(mem_ctx, servername, info2->printername, &printername);
4217 if (!W_ERROR_IS_OK(result)) {
4218 return result;
4221 copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4222 if (!r->devmode) {
4223 DEBUG(8,("Returning NULL Devicemode!\n"));
4226 compose_devicemode_devicename(r->devmode, printername);
4228 return WERR_OK;
4232 /********************************************************************
4233 ********************************************************************/
4235 static bool snum_is_shared_printer(int snum)
4237 return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4240 /********************************************************************
4241 Spoolss_enumprinters.
4242 ********************************************************************/
4244 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4245 const struct auth_serversupplied_info *session_info,
4246 struct messaging_context *msg_ctx,
4247 const char *servername,
4248 uint32_t level,
4249 uint32_t flags,
4250 union spoolss_PrinterInfo **info_p,
4251 uint32_t *count_p)
4253 int snum;
4254 int n_services = lp_numservices();
4255 union spoolss_PrinterInfo *info = NULL;
4256 uint32_t count = 0;
4257 WERROR result = WERR_OK;
4258 struct dcerpc_binding_handle *b = NULL;
4260 *count_p = 0;
4261 *info_p = NULL;
4263 for (snum = 0; snum < n_services; snum++) {
4265 const char *printer;
4266 struct spoolss_PrinterInfo2 *info2;
4268 if (!snum_is_shared_printer(snum)) {
4269 continue;
4272 printer = lp_const_servicename(snum);
4274 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4275 printer, snum));
4277 if (b == NULL) {
4278 result = winreg_printer_binding_handle(mem_ctx,
4279 session_info,
4280 msg_ctx,
4281 &b);
4282 if (!W_ERROR_IS_OK(result)) {
4283 goto out;
4287 result = winreg_create_printer(mem_ctx, b,
4288 printer);
4289 if (!W_ERROR_IS_OK(result)) {
4290 goto out;
4293 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4294 union spoolss_PrinterInfo,
4295 count + 1);
4296 if (!info) {
4297 result = WERR_NOMEM;
4298 goto out;
4301 result = winreg_get_printer(mem_ctx, b,
4302 printer, &info2);
4303 if (!W_ERROR_IS_OK(result)) {
4304 goto out;
4307 switch (level) {
4308 case 0:
4309 result = construct_printer_info0(info, session_info,
4310 msg_ctx, info2,
4311 servername,
4312 &info[count].info0, snum);
4313 break;
4314 case 1:
4315 result = construct_printer_info1(info, info2, flags,
4316 servername,
4317 &info[count].info1, snum);
4318 break;
4319 case 2:
4320 result = construct_printer_info2(info, msg_ctx, info2,
4321 servername,
4322 &info[count].info2, snum);
4323 break;
4324 case 4:
4325 result = construct_printer_info4(info, info2,
4326 servername,
4327 &info[count].info4, snum);
4328 break;
4329 case 5:
4330 result = construct_printer_info5(info, info2,
4331 servername,
4332 &info[count].info5, snum);
4333 break;
4335 default:
4336 result = WERR_UNKNOWN_LEVEL;
4337 goto out;
4340 if (!W_ERROR_IS_OK(result)) {
4341 goto out;
4344 count++;
4347 *count_p = count;
4348 *info_p = info;
4350 out:
4351 if (!W_ERROR_IS_OK(result)) {
4352 TALLOC_FREE(info);
4353 return result;
4356 *info_p = info;
4358 return WERR_OK;
4361 /********************************************************************
4362 * handle enumeration of printers at level 0
4363 ********************************************************************/
4365 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4366 const struct auth_serversupplied_info *session_info,
4367 struct messaging_context *msg_ctx,
4368 uint32_t flags,
4369 const char *servername,
4370 union spoolss_PrinterInfo **info,
4371 uint32_t *count)
4373 DEBUG(4,("enum_all_printers_info_0\n"));
4375 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4376 servername, 0, flags, info, count);
4380 /********************************************************************
4381 ********************************************************************/
4383 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4384 const struct auth_serversupplied_info *session_info,
4385 struct messaging_context *msg_ctx,
4386 const char *servername,
4387 uint32_t flags,
4388 union spoolss_PrinterInfo **info,
4389 uint32_t *count)
4391 DEBUG(4,("enum_all_printers_info_1\n"));
4393 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4394 servername, 1, flags, info, count);
4397 /********************************************************************
4398 enum_all_printers_info_1_local.
4399 *********************************************************************/
4401 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4402 const struct auth_serversupplied_info *session_info,
4403 struct messaging_context *msg_ctx,
4404 const char *servername,
4405 union spoolss_PrinterInfo **info,
4406 uint32_t *count)
4408 DEBUG(4,("enum_all_printers_info_1_local\n"));
4410 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4411 servername, PRINTER_ENUM_ICON8, info, count);
4414 /********************************************************************
4415 enum_all_printers_info_1_name.
4416 *********************************************************************/
4418 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4419 const struct auth_serversupplied_info *session_info,
4420 struct messaging_context *msg_ctx,
4421 const char *servername,
4422 union spoolss_PrinterInfo **info,
4423 uint32_t *count)
4425 const char *s = servername;
4427 DEBUG(4,("enum_all_printers_info_1_name\n"));
4429 if ((servername[0] == '\\') && (servername[1] == '\\')) {
4430 s = servername + 2;
4433 if (!is_myname_or_ipaddr(s)) {
4434 return WERR_INVALID_NAME;
4437 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4438 servername, PRINTER_ENUM_ICON8, info, count);
4441 /********************************************************************
4442 enum_all_printers_info_1_network.
4443 *********************************************************************/
4445 static WERROR enum_all_printers_info_1_network(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 const char *s = servername;
4454 DEBUG(4,("enum_all_printers_info_1_network\n"));
4456 /* If we respond to a enum_printers level 1 on our name with flags
4457 set to PRINTER_ENUM_REMOTE with a list of printers then these
4458 printers incorrectly appear in the APW browse list.
4459 Specifically the printers for the server appear at the workgroup
4460 level where all the other servers in the domain are
4461 listed. Windows responds to this call with a
4462 WERR_CAN_NOT_COMPLETE so we should do the same. */
4464 if (servername[0] == '\\' && servername[1] == '\\') {
4465 s = servername + 2;
4468 if (is_myname_or_ipaddr(s)) {
4469 return WERR_CAN_NOT_COMPLETE;
4472 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4473 servername, PRINTER_ENUM_NAME, info, count);
4476 /********************************************************************
4477 * api_spoolss_enumprinters
4479 * called from api_spoolss_enumprinters (see this to understand)
4480 ********************************************************************/
4482 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4483 const struct auth_serversupplied_info *session_info,
4484 struct messaging_context *msg_ctx,
4485 const char *servername,
4486 union spoolss_PrinterInfo **info,
4487 uint32_t *count)
4489 DEBUG(4,("enum_all_printers_info_2\n"));
4491 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4492 servername, 2, 0, info, count);
4495 /********************************************************************
4496 * handle enumeration of printers at level 1
4497 ********************************************************************/
4499 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4500 const struct auth_serversupplied_info *session_info,
4501 struct messaging_context *msg_ctx,
4502 uint32_t flags,
4503 const char *servername,
4504 union spoolss_PrinterInfo **info,
4505 uint32_t *count)
4507 /* Not all the flags are equals */
4509 if (flags & PRINTER_ENUM_LOCAL) {
4510 return enum_all_printers_info_1_local(mem_ctx, session_info,
4511 msg_ctx, servername, info, count);
4514 if (flags & PRINTER_ENUM_NAME) {
4515 return enum_all_printers_info_1_name(mem_ctx, session_info,
4516 msg_ctx, servername, info,
4517 count);
4520 if (flags & PRINTER_ENUM_NETWORK) {
4521 return enum_all_printers_info_1_network(mem_ctx, session_info,
4522 msg_ctx, servername, info,
4523 count);
4526 return WERR_OK; /* NT4sp5 does that */
4529 /********************************************************************
4530 * handle enumeration of printers at level 2
4531 ********************************************************************/
4533 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4534 const struct auth_serversupplied_info *session_info,
4535 struct messaging_context *msg_ctx,
4536 uint32_t flags,
4537 const char *servername,
4538 union spoolss_PrinterInfo **info,
4539 uint32_t *count)
4541 if (flags & PRINTER_ENUM_LOCAL) {
4543 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4544 servername,
4545 info, count);
4548 if (flags & PRINTER_ENUM_NAME) {
4549 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4550 return WERR_INVALID_NAME;
4553 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4554 servername,
4555 info, count);
4558 if (flags & PRINTER_ENUM_REMOTE) {
4559 return WERR_UNKNOWN_LEVEL;
4562 return WERR_OK;
4565 /********************************************************************
4566 * handle enumeration of printers at level 4
4567 ********************************************************************/
4569 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4570 const struct auth_serversupplied_info *session_info,
4571 struct messaging_context *msg_ctx,
4572 uint32_t flags,
4573 const char *servername,
4574 union spoolss_PrinterInfo **info,
4575 uint32_t *count)
4577 DEBUG(4,("enum_all_printers_info_4\n"));
4579 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4580 servername, 4, flags, info, count);
4584 /********************************************************************
4585 * handle enumeration of printers at level 5
4586 ********************************************************************/
4588 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4589 const struct auth_serversupplied_info *session_info,
4590 struct messaging_context *msg_ctx,
4591 uint32_t flags,
4592 const char *servername,
4593 union spoolss_PrinterInfo **info,
4594 uint32_t *count)
4596 DEBUG(4,("enum_all_printers_info_5\n"));
4598 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4599 servername, 5, flags, info, count);
4602 /****************************************************************
4603 _spoolss_EnumPrinters
4604 ****************************************************************/
4606 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4607 struct spoolss_EnumPrinters *r)
4609 const struct auth_serversupplied_info *session_info = get_session_info_system();
4610 WERROR result;
4612 /* that's an [in out] buffer */
4614 if (!r->in.buffer && (r->in.offered != 0)) {
4615 return WERR_INVALID_PARAM;
4618 DEBUG(4,("_spoolss_EnumPrinters\n"));
4620 *r->out.needed = 0;
4621 *r->out.count = 0;
4622 *r->out.info = NULL;
4625 * Level 1:
4626 * flags==PRINTER_ENUM_NAME
4627 * if name=="" then enumerates all printers
4628 * if name!="" then enumerate the printer
4629 * flags==PRINTER_ENUM_REMOTE
4630 * name is NULL, enumerate printers
4631 * Level 2: name!="" enumerates printers, name can't be NULL
4632 * Level 3: doesn't exist
4633 * Level 4: does a local registry lookup
4634 * Level 5: same as Level 2
4637 if (r->in.server && r->in.server[0] == '\0') {
4638 r->in.server = NULL;
4641 switch (r->in.level) {
4642 case 0:
4643 result = enumprinters_level0(p->mem_ctx, session_info,
4644 p->msg_ctx, r->in.flags,
4645 r->in.server,
4646 r->out.info, r->out.count);
4647 break;
4648 case 1:
4649 result = enumprinters_level1(p->mem_ctx, session_info,
4650 p->msg_ctx, r->in.flags,
4651 r->in.server,
4652 r->out.info, r->out.count);
4653 break;
4654 case 2:
4655 result = enumprinters_level2(p->mem_ctx, session_info,
4656 p->msg_ctx, r->in.flags,
4657 r->in.server,
4658 r->out.info, r->out.count);
4659 break;
4660 case 4:
4661 result = enumprinters_level4(p->mem_ctx, session_info,
4662 p->msg_ctx, r->in.flags,
4663 r->in.server,
4664 r->out.info, r->out.count);
4665 break;
4666 case 5:
4667 result = enumprinters_level5(p->mem_ctx, session_info,
4668 p->msg_ctx, r->in.flags,
4669 r->in.server,
4670 r->out.info, r->out.count);
4671 break;
4672 default:
4673 return WERR_UNKNOWN_LEVEL;
4676 if (!W_ERROR_IS_OK(result)) {
4677 return result;
4680 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4681 spoolss_EnumPrinters,
4682 *r->out.info, r->in.level,
4683 *r->out.count);
4684 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4685 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4687 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4690 /****************************************************************
4691 _spoolss_GetPrinter
4692 ****************************************************************/
4694 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4695 struct spoolss_GetPrinter *r)
4697 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4698 struct spoolss_PrinterInfo2 *info2 = NULL;
4699 WERROR result = WERR_OK;
4700 int snum;
4702 /* that's an [in out] buffer */
4704 if (!r->in.buffer && (r->in.offered != 0)) {
4705 return WERR_INVALID_PARAM;
4708 *r->out.needed = 0;
4710 if (Printer == NULL) {
4711 return WERR_BADFID;
4714 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4715 return WERR_BADFID;
4718 result = winreg_get_printer_internal(p->mem_ctx,
4719 get_session_info_system(),
4720 p->msg_ctx,
4721 lp_const_servicename(snum),
4722 &info2);
4723 if (!W_ERROR_IS_OK(result)) {
4724 goto out;
4727 switch (r->in.level) {
4728 case 0:
4729 result = construct_printer_info0(p->mem_ctx,
4730 get_session_info_system(),
4731 p->msg_ctx,
4732 info2,
4733 Printer->servername,
4734 &r->out.info->info0,
4735 snum);
4736 break;
4737 case 1:
4738 result = construct_printer_info1(p->mem_ctx, info2,
4739 PRINTER_ENUM_ICON8,
4740 Printer->servername,
4741 &r->out.info->info1, snum);
4742 break;
4743 case 2:
4744 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4745 Printer->servername,
4746 &r->out.info->info2, snum);
4747 break;
4748 case 3:
4749 result = construct_printer_info3(p->mem_ctx, info2,
4750 Printer->servername,
4751 &r->out.info->info3, snum);
4752 break;
4753 case 4:
4754 result = construct_printer_info4(p->mem_ctx, info2,
4755 Printer->servername,
4756 &r->out.info->info4, snum);
4757 break;
4758 case 5:
4759 result = construct_printer_info5(p->mem_ctx, info2,
4760 Printer->servername,
4761 &r->out.info->info5, snum);
4762 break;
4763 case 6:
4764 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4765 Printer->servername,
4766 &r->out.info->info6, snum);
4767 break;
4768 case 7:
4769 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4770 Printer->servername,
4771 &r->out.info->info7, snum);
4772 break;
4773 case 8:
4774 result = construct_printer_info8(p->mem_ctx, info2,
4775 Printer->servername,
4776 &r->out.info->info8, snum);
4777 break;
4778 default:
4779 result = WERR_UNKNOWN_LEVEL;
4780 break;
4783 out:
4784 if (!W_ERROR_IS_OK(result)) {
4785 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4786 r->in.level, win_errstr(result)));
4787 TALLOC_FREE(r->out.info);
4788 return result;
4791 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4792 r->out.info, r->in.level);
4793 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4795 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4798 /********************************************************************
4799 ********************************************************************/
4801 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4802 do { \
4803 if (in && strlen(in)) { \
4804 out = talloc_strdup(mem_ctx, in); \
4805 } else { \
4806 out = talloc_strdup(mem_ctx, ""); \
4808 W_ERROR_HAVE_NO_MEMORY(out); \
4809 } while (0);
4811 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4812 do { \
4813 if (in && strlen(in)) { \
4814 out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4815 } else { \
4816 out = talloc_strdup(mem_ctx, ""); \
4818 W_ERROR_HAVE_NO_MEMORY(out); \
4819 } while (0);
4821 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4822 const char **string_array,
4823 const char ***presult,
4824 const char *cservername,
4825 const char *arch,
4826 int version)
4828 int i, num_strings = 0;
4829 const char **array = NULL;
4831 if (string_array == NULL) {
4832 return WERR_INVALID_PARAMETER;
4835 for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4836 const char *str = NULL;
4838 if (cservername == NULL || arch == NULL) {
4839 FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4840 } else {
4841 FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4844 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4845 TALLOC_FREE(array);
4846 return WERR_NOMEM;
4850 if (i > 0) {
4851 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4852 &array, &num_strings);
4855 if (presult) {
4856 *presult = array;
4859 return WERR_OK;
4862 /********************************************************************
4863 * fill a spoolss_DriverInfo1 struct
4864 ********************************************************************/
4866 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4867 struct spoolss_DriverInfo1 *r,
4868 const struct spoolss_DriverInfo8 *driver,
4869 const char *servername)
4871 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4872 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4874 return WERR_OK;
4877 /********************************************************************
4878 * fill a spoolss_DriverInfo2 struct
4879 ********************************************************************/
4881 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4882 struct spoolss_DriverInfo2 *r,
4883 const struct spoolss_DriverInfo8 *driver,
4884 const char *servername)
4887 const char *cservername = canon_servername(servername);
4889 r->version = driver->version;
4891 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4892 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4893 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4894 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4896 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4897 driver->architecture,
4898 driver->version,
4899 driver->driver_path,
4900 r->driver_path);
4902 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4903 driver->architecture,
4904 driver->version,
4905 driver->data_file,
4906 r->data_file);
4908 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4909 driver->architecture,
4910 driver->version,
4911 driver->config_file,
4912 r->config_file);
4914 return WERR_OK;
4917 /********************************************************************
4918 * fill a spoolss_DriverInfo3 struct
4919 ********************************************************************/
4921 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4922 struct spoolss_DriverInfo3 *r,
4923 const struct spoolss_DriverInfo8 *driver,
4924 const char *servername)
4926 const char *cservername = canon_servername(servername);
4928 r->version = driver->version;
4930 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4931 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4932 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4933 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4935 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4936 driver->architecture,
4937 driver->version,
4938 driver->driver_path,
4939 r->driver_path);
4941 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4942 driver->architecture,
4943 driver->version,
4944 driver->data_file,
4945 r->data_file);
4947 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4948 driver->architecture,
4949 driver->version,
4950 driver->config_file,
4951 r->config_file);
4953 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4954 driver->architecture,
4955 driver->version,
4956 driver->help_file,
4957 r->help_file);
4959 FILL_DRIVER_STRING(mem_ctx,
4960 driver->monitor_name,
4961 r->monitor_name);
4963 FILL_DRIVER_STRING(mem_ctx,
4964 driver->default_datatype,
4965 r->default_datatype);
4967 return string_array_from_driver_info(mem_ctx,
4968 driver->dependent_files,
4969 &r->dependent_files,
4970 cservername,
4971 driver->architecture,
4972 driver->version);
4975 /********************************************************************
4976 * fill a spoolss_DriverInfo4 struct
4977 ********************************************************************/
4979 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4980 struct spoolss_DriverInfo4 *r,
4981 const struct spoolss_DriverInfo8 *driver,
4982 const char *servername)
4984 const char *cservername = canon_servername(servername);
4985 WERROR result;
4987 r->version = driver->version;
4989 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4990 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4991 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4992 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4994 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4995 driver->architecture,
4996 driver->version,
4997 driver->driver_path,
4998 r->driver_path);
5000 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5001 driver->architecture,
5002 driver->version,
5003 driver->data_file,
5004 r->data_file);
5006 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5007 driver->architecture,
5008 driver->version,
5009 driver->config_file,
5010 r->config_file);
5012 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5013 driver->architecture,
5014 driver->version,
5015 driver->help_file,
5016 r->help_file);
5018 result = string_array_from_driver_info(mem_ctx,
5019 driver->dependent_files,
5020 &r->dependent_files,
5021 cservername,
5022 driver->architecture,
5023 driver->version);
5024 if (!W_ERROR_IS_OK(result)) {
5025 return result;
5028 FILL_DRIVER_STRING(mem_ctx,
5029 driver->monitor_name,
5030 r->monitor_name);
5032 FILL_DRIVER_STRING(mem_ctx,
5033 driver->default_datatype,
5034 r->default_datatype);
5037 result = string_array_from_driver_info(mem_ctx,
5038 driver->previous_names,
5039 &r->previous_names,
5040 NULL, NULL, 0);
5042 return result;
5045 /********************************************************************
5046 * fill a spoolss_DriverInfo5 struct
5047 ********************************************************************/
5049 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5050 struct spoolss_DriverInfo5 *r,
5051 const struct spoolss_DriverInfo8 *driver,
5052 const char *servername)
5054 const char *cservername = canon_servername(servername);
5056 r->version = driver->version;
5058 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5059 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5060 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5061 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5063 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5064 driver->architecture,
5065 driver->version,
5066 driver->driver_path,
5067 r->driver_path);
5069 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5070 driver->architecture,
5071 driver->version,
5072 driver->data_file,
5073 r->data_file);
5075 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5076 driver->architecture,
5077 driver->version,
5078 driver->config_file,
5079 r->config_file);
5081 r->driver_attributes = 0;
5082 r->config_version = 0;
5083 r->driver_version = 0;
5085 return WERR_OK;
5087 /********************************************************************
5088 * fill a spoolss_DriverInfo6 struct
5089 ********************************************************************/
5091 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5092 struct spoolss_DriverInfo6 *r,
5093 const struct spoolss_DriverInfo8 *driver,
5094 const char *servername)
5096 const char *cservername = canon_servername(servername);
5097 WERROR result;
5099 r->version = driver->version;
5101 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5102 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5103 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5104 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5106 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5107 driver->architecture,
5108 driver->version,
5109 driver->driver_path,
5110 r->driver_path);
5112 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5113 driver->architecture,
5114 driver->version,
5115 driver->data_file,
5116 r->data_file);
5118 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5119 driver->architecture,
5120 driver->version,
5121 driver->config_file,
5122 r->config_file);
5124 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5125 driver->architecture,
5126 driver->version,
5127 driver->help_file,
5128 r->help_file);
5130 FILL_DRIVER_STRING(mem_ctx,
5131 driver->monitor_name,
5132 r->monitor_name);
5134 FILL_DRIVER_STRING(mem_ctx,
5135 driver->default_datatype,
5136 r->default_datatype);
5138 result = string_array_from_driver_info(mem_ctx,
5139 driver->dependent_files,
5140 &r->dependent_files,
5141 cservername,
5142 driver->architecture,
5143 driver->version);
5144 if (!W_ERROR_IS_OK(result)) {
5145 return result;
5148 result = string_array_from_driver_info(mem_ctx,
5149 driver->previous_names,
5150 &r->previous_names,
5151 NULL, NULL, 0);
5152 if (!W_ERROR_IS_OK(result)) {
5153 return result;
5156 r->driver_date = driver->driver_date;
5157 r->driver_version = driver->driver_version;
5159 FILL_DRIVER_STRING(mem_ctx,
5160 driver->manufacturer_name,
5161 r->manufacturer_name);
5162 FILL_DRIVER_STRING(mem_ctx,
5163 driver->manufacturer_url,
5164 r->manufacturer_url);
5165 FILL_DRIVER_STRING(mem_ctx,
5166 driver->hardware_id,
5167 r->hardware_id);
5168 FILL_DRIVER_STRING(mem_ctx,
5169 driver->provider,
5170 r->provider);
5172 return WERR_OK;
5175 /********************************************************************
5176 * fill a spoolss_DriverInfo8 struct
5177 ********************************************************************/
5179 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5180 struct spoolss_DriverInfo8 *r,
5181 const struct spoolss_DriverInfo8 *driver,
5182 const char *servername)
5184 const char *cservername = canon_servername(servername);
5185 WERROR result;
5187 r->version = driver->version;
5189 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5190 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5191 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5192 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5194 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5195 driver->architecture,
5196 driver->version,
5197 driver->driver_path,
5198 r->driver_path);
5200 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5201 driver->architecture,
5202 driver->version,
5203 driver->data_file,
5204 r->data_file);
5206 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5207 driver->architecture,
5208 driver->version,
5209 driver->config_file,
5210 r->config_file);
5212 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5213 driver->architecture,
5214 driver->version,
5215 driver->help_file,
5216 r->help_file);
5218 FILL_DRIVER_STRING(mem_ctx,
5219 driver->monitor_name,
5220 r->monitor_name);
5222 FILL_DRIVER_STRING(mem_ctx,
5223 driver->default_datatype,
5224 r->default_datatype);
5226 result = string_array_from_driver_info(mem_ctx,
5227 driver->dependent_files,
5228 &r->dependent_files,
5229 cservername,
5230 driver->architecture,
5231 driver->version);
5232 if (!W_ERROR_IS_OK(result)) {
5233 return result;
5236 result = string_array_from_driver_info(mem_ctx,
5237 driver->previous_names,
5238 &r->previous_names,
5239 NULL, NULL, 0);
5240 if (!W_ERROR_IS_OK(result)) {
5241 return result;
5244 r->driver_date = driver->driver_date;
5245 r->driver_version = driver->driver_version;
5247 FILL_DRIVER_STRING(mem_ctx,
5248 driver->manufacturer_name,
5249 r->manufacturer_name);
5250 FILL_DRIVER_STRING(mem_ctx,
5251 driver->manufacturer_url,
5252 r->manufacturer_url);
5253 FILL_DRIVER_STRING(mem_ctx,
5254 driver->hardware_id,
5255 r->hardware_id);
5256 FILL_DRIVER_STRING(mem_ctx,
5257 driver->provider,
5258 r->provider);
5260 FILL_DRIVER_STRING(mem_ctx,
5261 driver->print_processor,
5262 r->print_processor);
5263 FILL_DRIVER_STRING(mem_ctx,
5264 driver->vendor_setup,
5265 r->vendor_setup);
5267 result = string_array_from_driver_info(mem_ctx,
5268 driver->color_profiles,
5269 &r->color_profiles,
5270 NULL, NULL, 0);
5271 if (!W_ERROR_IS_OK(result)) {
5272 return result;
5275 FILL_DRIVER_STRING(mem_ctx,
5276 driver->inf_path,
5277 r->inf_path);
5279 r->printer_driver_attributes = driver->printer_driver_attributes;
5281 result = string_array_from_driver_info(mem_ctx,
5282 driver->core_driver_dependencies,
5283 &r->core_driver_dependencies,
5284 NULL, NULL, 0);
5285 if (!W_ERROR_IS_OK(result)) {
5286 return result;
5289 r->min_inbox_driver_ver_date = driver->min_inbox_driver_ver_date;
5290 r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5292 return WERR_OK;
5295 #if 0 /* disabled until marshalling issues are resolved - gd */
5296 /********************************************************************
5297 ********************************************************************/
5299 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5300 struct spoolss_DriverFileInfo *r,
5301 const char *cservername,
5302 const char *file_name,
5303 enum spoolss_DriverFileType file_type,
5304 uint32_t file_version)
5306 r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
5307 cservername, file_name);
5308 W_ERROR_HAVE_NO_MEMORY(r->file_name);
5309 r->file_type = file_type;
5310 r->file_version = file_version;
5312 return WERR_OK;
5315 /********************************************************************
5316 ********************************************************************/
5318 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5319 const struct spoolss_DriverInfo8 *driver,
5320 const char *cservername,
5321 struct spoolss_DriverFileInfo **info_p,
5322 uint32_t *count_p)
5324 struct spoolss_DriverFileInfo *info = NULL;
5325 uint32_t count = 0;
5326 WERROR result;
5327 uint32_t i;
5329 *info_p = NULL;
5330 *count_p = 0;
5332 if (strlen(driver->driver_path)) {
5333 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5334 struct spoolss_DriverFileInfo,
5335 count + 1);
5336 W_ERROR_HAVE_NO_MEMORY(info);
5337 result = fill_spoolss_DriverFileInfo(info,
5338 &info[count],
5339 cservername,
5340 driver->driver_path,
5341 SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5343 W_ERROR_NOT_OK_RETURN(result);
5344 count++;
5347 if (strlen(driver->config_file)) {
5348 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5349 struct spoolss_DriverFileInfo,
5350 count + 1);
5351 W_ERROR_HAVE_NO_MEMORY(info);
5352 result = fill_spoolss_DriverFileInfo(info,
5353 &info[count],
5354 cservername,
5355 driver->config_file,
5356 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5358 W_ERROR_NOT_OK_RETURN(result);
5359 count++;
5362 if (strlen(driver->data_file)) {
5363 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5364 struct spoolss_DriverFileInfo,
5365 count + 1);
5366 W_ERROR_HAVE_NO_MEMORY(info);
5367 result = fill_spoolss_DriverFileInfo(info,
5368 &info[count],
5369 cservername,
5370 driver->data_file,
5371 SPOOLSS_DRIVER_FILE_TYPE_DATA,
5373 W_ERROR_NOT_OK_RETURN(result);
5374 count++;
5377 if (strlen(driver->help_file)) {
5378 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5379 struct spoolss_DriverFileInfo,
5380 count + 1);
5381 W_ERROR_HAVE_NO_MEMORY(info);
5382 result = fill_spoolss_DriverFileInfo(info,
5383 &info[count],
5384 cservername,
5385 driver->help_file,
5386 SPOOLSS_DRIVER_FILE_TYPE_HELP,
5388 W_ERROR_NOT_OK_RETURN(result);
5389 count++;
5392 for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5393 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5394 struct spoolss_DriverFileInfo,
5395 count + 1);
5396 W_ERROR_HAVE_NO_MEMORY(info);
5397 result = fill_spoolss_DriverFileInfo(info,
5398 &info[count],
5399 cservername,
5400 driver->dependent_files[i],
5401 SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5403 W_ERROR_NOT_OK_RETURN(result);
5404 count++;
5407 *info_p = info;
5408 *count_p = count;
5410 return WERR_OK;
5413 /********************************************************************
5414 * fill a spoolss_DriverInfo101 struct
5415 ********************************************************************/
5417 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5418 struct spoolss_DriverInfo101 *r,
5419 const struct spoolss_DriverInfo8 *driver,
5420 const char *servername)
5422 const char *cservername = canon_servername(servername);
5423 WERROR result;
5425 r->version = driver->version;
5427 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5428 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5429 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5430 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5432 result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5433 cservername,
5434 &r->file_info,
5435 &r->file_count);
5436 if (!W_ERROR_IS_OK(result)) {
5437 return result;
5440 FILL_DRIVER_STRING(mem_ctx,
5441 driver->monitor_name,
5442 r->monitor_name);
5444 FILL_DRIVER_STRING(mem_ctx,
5445 driver->default_datatype,
5446 r->default_datatype);
5448 result = string_array_from_driver_info(mem_ctx,
5449 driver->previous_names,
5450 &r->previous_names,
5451 NULL, NULL, 0);
5452 if (!W_ERROR_IS_OK(result)) {
5453 return result;
5456 r->driver_date = driver->driver_date;
5457 r->driver_version = driver->driver_version;
5459 FILL_DRIVER_STRING(mem_ctx,
5460 driver->manufacturer_name,
5461 r->manufacturer_name);
5462 FILL_DRIVER_STRING(mem_ctx,
5463 driver->manufacturer_url,
5464 r->manufacturer_url);
5465 FILL_DRIVER_STRING(mem_ctx,
5466 driver->hardware_id,
5467 r->hardware_id);
5468 FILL_DRIVER_STRING(mem_ctx,
5469 driver->provider,
5470 r->provider);
5472 return WERR_OK;
5474 #endif
5475 /********************************************************************
5476 ********************************************************************/
5478 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5479 const struct auth_serversupplied_info *session_info,
5480 struct messaging_context *msg_ctx,
5481 uint32_t level,
5482 union spoolss_DriverInfo *r,
5483 int snum,
5484 const char *servername,
5485 const char *architecture,
5486 uint32_t version)
5488 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5489 struct spoolss_DriverInfo8 *driver;
5490 WERROR result;
5491 struct dcerpc_binding_handle *b;
5493 if (level == 101) {
5494 return WERR_UNKNOWN_LEVEL;
5497 result = winreg_printer_binding_handle(mem_ctx,
5498 session_info,
5499 msg_ctx,
5500 &b);
5501 if (!W_ERROR_IS_OK(result)) {
5502 return result;
5505 result = winreg_get_printer(mem_ctx, b,
5506 lp_const_servicename(snum),
5507 &pinfo2);
5509 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5510 win_errstr(result)));
5512 if (!W_ERROR_IS_OK(result)) {
5513 return WERR_INVALID_PRINTER_NAME;
5516 result = winreg_get_driver(mem_ctx, b,
5517 architecture,
5518 pinfo2->drivername, version, &driver);
5520 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5521 win_errstr(result)));
5523 if (!W_ERROR_IS_OK(result)) {
5525 * Is this a W2k client ?
5528 if (version < 3) {
5529 talloc_free(pinfo2);
5530 return WERR_UNKNOWN_PRINTER_DRIVER;
5533 /* Yes - try again with a WinNT driver. */
5534 version = 2;
5535 result = winreg_get_driver(mem_ctx, b,
5536 architecture,
5537 pinfo2->drivername,
5538 version, &driver);
5539 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5540 win_errstr(result)));
5541 if (!W_ERROR_IS_OK(result)) {
5542 talloc_free(pinfo2);
5543 return WERR_UNKNOWN_PRINTER_DRIVER;
5547 switch (level) {
5548 case 1:
5549 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5550 break;
5551 case 2:
5552 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5553 break;
5554 case 3:
5555 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5556 break;
5557 case 4:
5558 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5559 break;
5560 case 5:
5561 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5562 break;
5563 case 6:
5564 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5565 break;
5566 case 8:
5567 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5568 break;
5569 #if 0 /* disabled until marshalling issues are resolved - gd */
5570 case 101:
5571 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5572 break;
5573 #endif
5574 default:
5575 result = WERR_UNKNOWN_LEVEL;
5576 break;
5579 talloc_free(pinfo2);
5580 talloc_free(driver);
5582 return result;
5585 /****************************************************************
5586 _spoolss_GetPrinterDriver2
5587 ****************************************************************/
5589 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5590 struct spoolss_GetPrinterDriver2 *r)
5592 struct printer_handle *printer;
5593 WERROR result;
5595 int snum;
5597 /* that's an [in out] buffer */
5599 if (!r->in.buffer && (r->in.offered != 0)) {
5600 return WERR_INVALID_PARAM;
5603 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5605 if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5606 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5607 return WERR_INVALID_PRINTER_NAME;
5610 *r->out.needed = 0;
5611 *r->out.server_major_version = 0;
5612 *r->out.server_minor_version = 0;
5614 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5615 return WERR_BADFID;
5618 result = construct_printer_driver_info_level(p->mem_ctx,
5619 get_session_info_system(),
5620 p->msg_ctx,
5621 r->in.level, r->out.info,
5622 snum, printer->servername,
5623 r->in.architecture,
5624 r->in.client_major_version);
5625 if (!W_ERROR_IS_OK(result)) {
5626 TALLOC_FREE(r->out.info);
5627 return result;
5630 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5631 r->out.info, r->in.level);
5632 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5634 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5638 /****************************************************************
5639 _spoolss_StartPagePrinter
5640 ****************************************************************/
5642 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5643 struct spoolss_StartPagePrinter *r)
5645 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5647 if (!Printer) {
5648 DEBUG(3,("_spoolss_StartPagePrinter: "
5649 "Error in startpageprinter printer handle\n"));
5650 return WERR_BADFID;
5653 Printer->page_started = true;
5654 return WERR_OK;
5657 /****************************************************************
5658 _spoolss_EndPagePrinter
5659 ****************************************************************/
5661 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5662 struct spoolss_EndPagePrinter *r)
5664 int snum;
5666 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5668 if (!Printer) {
5669 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5670 OUR_HANDLE(r->in.handle)));
5671 return WERR_BADFID;
5674 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5675 return WERR_BADFID;
5677 Printer->page_started = false;
5678 print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5680 return WERR_OK;
5683 /****************************************************************
5684 _spoolss_StartDocPrinter
5685 ****************************************************************/
5687 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5688 struct spoolss_StartDocPrinter *r)
5690 struct spoolss_DocumentInfo1 *info_1;
5691 int snum;
5692 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5693 WERROR werr;
5695 if (!Printer) {
5696 DEBUG(2,("_spoolss_StartDocPrinter: "
5697 "Invalid handle (%s:%u:%u)\n",
5698 OUR_HANDLE(r->in.handle)));
5699 return WERR_BADFID;
5702 if (Printer->jobid) {
5703 DEBUG(2, ("_spoolss_StartDocPrinter: "
5704 "StartDocPrinter called twice! "
5705 "(existing jobid = %d)\n", Printer->jobid));
5706 return WERR_INVALID_HANDLE;
5709 if (r->in.level != 1) {
5710 return WERR_UNKNOWN_LEVEL;
5713 info_1 = r->in.info.info1;
5716 * a nice thing with NT is it doesn't listen to what you tell it.
5717 * when asked to send _only_ RAW datas, it tries to send datas
5718 * in EMF format.
5720 * So I add checks like in NT Server ...
5723 if (info_1->datatype) {
5724 if (strcmp(info_1->datatype, "RAW") != 0) {
5725 *r->out.job_id = 0;
5726 return WERR_INVALID_DATATYPE;
5730 /* get the share number of the printer */
5731 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5732 return WERR_BADFID;
5735 werr = print_job_start(p->session_info,
5736 p->msg_ctx,
5737 p->client_id->name,
5738 snum,
5739 info_1->document_name,
5740 info_1->output_file,
5741 Printer->devmode,
5742 &Printer->jobid);
5744 /* An error occured in print_job_start() so return an appropriate
5745 NT error code. */
5747 if (!W_ERROR_IS_OK(werr)) {
5748 return werr;
5751 Printer->document_started = true;
5752 *r->out.job_id = Printer->jobid;
5754 return WERR_OK;
5757 /****************************************************************
5758 _spoolss_EndDocPrinter
5759 ****************************************************************/
5761 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5762 struct spoolss_EndDocPrinter *r)
5764 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5765 NTSTATUS status;
5766 int snum;
5768 if (!Printer) {
5769 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5770 OUR_HANDLE(r->in.handle)));
5771 return WERR_BADFID;
5774 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5775 return WERR_BADFID;
5778 Printer->document_started = false;
5779 status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5780 if (!NT_STATUS_IS_OK(status)) {
5781 DEBUG(2, ("_spoolss_EndDocPrinter: "
5782 "print_job_end failed [%s]\n",
5783 nt_errstr(status)));
5786 Printer->jobid = 0;
5787 return ntstatus_to_werror(status);
5790 /****************************************************************
5791 _spoolss_WritePrinter
5792 ****************************************************************/
5794 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5795 struct spoolss_WritePrinter *r)
5797 ssize_t buffer_written;
5798 int snum;
5799 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5801 if (!Printer) {
5802 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5803 OUR_HANDLE(r->in.handle)));
5804 *r->out.num_written = r->in._data_size;
5805 return WERR_BADFID;
5808 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5809 return WERR_BADFID;
5811 /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5812 buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5813 snum, Printer->jobid,
5814 (const char *)r->in.data.data,
5815 (size_t)r->in._data_size);
5816 if (buffer_written == (ssize_t)-1) {
5817 *r->out.num_written = 0;
5818 if (errno == ENOSPC)
5819 return WERR_NO_SPOOL_SPACE;
5820 else
5821 return WERR_ACCESS_DENIED;
5824 *r->out.num_written = r->in._data_size;
5826 return WERR_OK;
5829 /********************************************************************
5830 * api_spoolss_getprinter
5831 * called from the spoolss dispatcher
5833 ********************************************************************/
5835 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5836 struct pipes_struct *p)
5838 const struct auth_serversupplied_info *session_info = p->session_info;
5839 int snum;
5840 WERROR errcode = WERR_BADFUNC;
5841 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5843 if (!Printer) {
5844 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5845 OUR_HANDLE(handle)));
5846 return WERR_BADFID;
5849 if (!get_printer_snum(p, handle, &snum, NULL))
5850 return WERR_BADFID;
5852 switch (command) {
5853 case SPOOLSS_PRINTER_CONTROL_PAUSE:
5854 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
5855 break;
5856 case SPOOLSS_PRINTER_CONTROL_RESUME:
5857 case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5858 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
5859 break;
5860 case SPOOLSS_PRINTER_CONTROL_PURGE:
5861 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
5862 break;
5863 default:
5864 return WERR_UNKNOWN_LEVEL;
5867 return errcode;
5871 /****************************************************************
5872 _spoolss_AbortPrinter
5873 * From MSDN: "Deletes printer's spool file if printer is configured
5874 * for spooling"
5875 ****************************************************************/
5877 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
5878 struct spoolss_AbortPrinter *r)
5880 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5881 int snum;
5882 WERROR errcode = WERR_OK;
5884 if (!Printer) {
5885 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5886 OUR_HANDLE(r->in.handle)));
5887 return WERR_BADFID;
5890 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5891 return WERR_BADFID;
5893 if (!Printer->document_started) {
5894 return WERR_SPL_NO_STARTDOC;
5897 errcode = print_job_delete(p->session_info,
5898 p->msg_ctx,
5899 snum,
5900 Printer->jobid);
5902 return errcode;
5905 /********************************************************************
5906 * called by spoolss_api_setprinter
5907 * when updating a printer description
5908 ********************************************************************/
5910 static WERROR update_printer_sec(struct policy_handle *handle,
5911 struct pipes_struct *p,
5912 struct sec_desc_buf *secdesc_ctr)
5914 struct spoolss_security_descriptor *new_secdesc = NULL;
5915 struct spoolss_security_descriptor *old_secdesc = NULL;
5916 const char *printer;
5917 WERROR result;
5918 int snum;
5919 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5920 struct dcerpc_binding_handle *b;
5922 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5923 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5924 OUR_HANDLE(handle)));
5926 result = WERR_BADFID;
5927 goto done;
5930 if (secdesc_ctr == NULL) {
5931 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5932 result = WERR_INVALID_PARAM;
5933 goto done;
5935 printer = lp_const_servicename(snum);
5937 /* Check the user has permissions to change the security
5938 descriptor. By experimentation with two NT machines, the user
5939 requires Full Access to the printer to change security
5940 information. */
5942 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5943 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5944 result = WERR_ACCESS_DENIED;
5945 goto done;
5948 result = winreg_printer_binding_handle(p->mem_ctx,
5949 get_session_info_system(),
5950 p->msg_ctx,
5951 &b);
5952 if (!W_ERROR_IS_OK(result)) {
5953 goto done;
5956 /* NT seems to like setting the security descriptor even though
5957 nothing may have actually changed. */
5958 result = winreg_get_printer_secdesc(p->mem_ctx, b,
5959 printer,
5960 &old_secdesc);
5961 if (!W_ERROR_IS_OK(result)) {
5962 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
5963 result = WERR_BADFID;
5964 goto done;
5967 if (DEBUGLEVEL >= 10) {
5968 struct security_acl *the_acl;
5969 int i;
5971 the_acl = old_secdesc->dacl;
5972 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5973 printer, the_acl->num_aces));
5975 for (i = 0; i < the_acl->num_aces; i++) {
5976 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5977 &the_acl->aces[i].trustee),
5978 the_acl->aces[i].access_mask));
5981 the_acl = secdesc_ctr->sd->dacl;
5983 if (the_acl) {
5984 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5985 printer, the_acl->num_aces));
5987 for (i = 0; i < the_acl->num_aces; i++) {
5988 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5989 &the_acl->aces[i].trustee),
5990 the_acl->aces[i].access_mask));
5992 } else {
5993 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5997 new_secdesc = sec_desc_merge(p->mem_ctx, secdesc_ctr->sd, old_secdesc);
5998 if (new_secdesc == NULL) {
5999 result = WERR_NOMEM;
6000 goto done;
6003 if (security_descriptor_equal(new_secdesc, old_secdesc)) {
6004 result = WERR_OK;
6005 goto done;
6008 result = winreg_set_printer_secdesc(p->mem_ctx, b,
6009 printer,
6010 new_secdesc);
6012 done:
6013 return result;
6016 /********************************************************************
6017 Canonicalize printer info from a client
6018 ********************************************************************/
6020 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
6021 struct spoolss_SetPrinterInfo2 *info2,
6022 int snum)
6024 fstring printername;
6025 const char *p;
6027 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6028 "portname=%s drivername=%s comment=%s location=%s\n",
6029 info2->servername, info2->printername, info2->sharename,
6030 info2->portname, info2->drivername, info2->comment,
6031 info2->location));
6033 /* we force some elements to "correct" values */
6034 info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
6035 if (info2->servername == NULL) {
6036 return false;
6038 info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6039 if (info2->sharename == NULL) {
6040 return false;
6043 /* check to see if we allow printername != sharename */
6044 if (lp_force_printername(snum)) {
6045 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6046 global_myname(), info2->sharename);
6047 } else {
6048 /* make sure printername is in \\server\printername format */
6049 fstrcpy(printername, info2->printername);
6050 p = printername;
6051 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6052 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6053 p++;
6056 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6057 global_myname(), p);
6059 if (info2->printername == NULL) {
6060 return false;
6063 info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6064 info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6066 return true;
6069 /****************************************************************************
6070 ****************************************************************************/
6072 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6074 char *cmd = lp_addport_cmd();
6075 char *command = NULL;
6076 int ret;
6077 bool is_print_op = false;
6079 if ( !*cmd ) {
6080 return WERR_ACCESS_DENIED;
6083 command = talloc_asprintf(ctx,
6084 "%s \"%s\" \"%s\"", cmd, portname, uri );
6085 if (!command) {
6086 return WERR_NOMEM;
6089 if ( token )
6090 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6092 DEBUG(10,("Running [%s]\n", command));
6094 /********* BEGIN SePrintOperatorPrivilege **********/
6096 if ( is_print_op )
6097 become_root();
6099 ret = smbrun(command, NULL);
6101 if ( is_print_op )
6102 unbecome_root();
6104 /********* END SePrintOperatorPrivilege **********/
6106 DEBUGADD(10,("returned [%d]\n", ret));
6108 TALLOC_FREE(command);
6110 if ( ret != 0 ) {
6111 return WERR_ACCESS_DENIED;
6114 return WERR_OK;
6117 /****************************************************************************
6118 ****************************************************************************/
6120 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6121 struct spoolss_SetPrinterInfo2 *info2,
6122 const char *remote_machine,
6123 struct messaging_context *msg_ctx)
6125 char *cmd = lp_addprinter_cmd();
6126 char **qlines;
6127 char *command = NULL;
6128 int numlines;
6129 int ret;
6130 int fd;
6131 bool is_print_op = false;
6133 if (!remote_machine) {
6134 return false;
6137 command = talloc_asprintf(ctx,
6138 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6139 cmd, info2->printername, info2->sharename,
6140 info2->portname, info2->drivername,
6141 info2->location, info2->comment, remote_machine);
6142 if (!command) {
6143 return false;
6146 if ( token )
6147 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6149 DEBUG(10,("Running [%s]\n", command));
6151 /********* BEGIN SePrintOperatorPrivilege **********/
6153 if ( is_print_op )
6154 become_root();
6156 if ( (ret = smbrun(command, &fd)) == 0 ) {
6157 /* Tell everyone we updated smb.conf. */
6158 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6161 if ( is_print_op )
6162 unbecome_root();
6164 /********* END SePrintOperatorPrivilege **********/
6166 DEBUGADD(10,("returned [%d]\n", ret));
6168 TALLOC_FREE(command);
6170 if ( ret != 0 ) {
6171 if (fd != -1)
6172 close(fd);
6173 return false;
6176 /* reload our services immediately */
6177 become_root();
6178 reload_services(msg_ctx, -1, false);
6179 unbecome_root();
6181 numlines = 0;
6182 /* Get lines and convert them back to dos-codepage */
6183 qlines = fd_lines_load(fd, &numlines, 0, NULL);
6184 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6185 close(fd);
6187 /* Set the portname to what the script says the portname should be. */
6188 /* but don't require anything to be return from the script exit a good error code */
6190 if (numlines) {
6191 /* Set the portname to what the script says the portname should be. */
6192 info2->portname = talloc_strdup(ctx, qlines[0]);
6193 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6196 TALLOC_FREE(qlines);
6197 return true;
6200 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6201 const struct auth_serversupplied_info *session_info,
6202 struct messaging_context *msg_ctx,
6203 int snum,
6204 struct spoolss_SetPrinterInfo2 *printer,
6205 struct spoolss_PrinterInfo2 *old_printer)
6207 bool force_update = (old_printer == NULL);
6208 const char *dnsdomname;
6209 const char *longname;
6210 const char *uncname;
6211 const char *spooling;
6212 DATA_BLOB buffer;
6213 WERROR result = WERR_OK;
6214 struct dcerpc_binding_handle *b;
6216 result = winreg_printer_binding_handle(mem_ctx,
6217 session_info,
6218 msg_ctx,
6219 &b);
6220 if (!W_ERROR_IS_OK(result)) {
6221 return result;
6224 if (force_update || !strequal(printer->drivername, old_printer->drivername)) {
6225 push_reg_sz(mem_ctx, &buffer, printer->drivername);
6226 winreg_set_printer_dataex(mem_ctx, b,
6227 printer->sharename,
6228 SPOOL_DSSPOOLER_KEY,
6229 SPOOL_REG_DRIVERNAME,
6230 REG_SZ,
6231 buffer.data,
6232 buffer.length);
6234 if (!force_update) {
6235 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6236 printer->drivername));
6238 notify_printer_driver(server_event_context(), msg_ctx,
6239 snum, printer->drivername ?
6240 printer->drivername : "");
6244 if (force_update || !strequal(printer->comment, old_printer->comment)) {
6245 push_reg_sz(mem_ctx, &buffer, printer->comment);
6246 winreg_set_printer_dataex(mem_ctx, b,
6247 printer->sharename,
6248 SPOOL_DSSPOOLER_KEY,
6249 SPOOL_REG_DESCRIPTION,
6250 REG_SZ,
6251 buffer.data,
6252 buffer.length);
6254 if (!force_update) {
6255 notify_printer_comment(server_event_context(), msg_ctx,
6256 snum, printer->comment ?
6257 printer->comment : "");
6261 if (force_update || !strequal(printer->sharename, old_printer->sharename)) {
6262 push_reg_sz(mem_ctx, &buffer, printer->sharename);
6263 winreg_set_printer_dataex(mem_ctx, b,
6264 printer->sharename,
6265 SPOOL_DSSPOOLER_KEY,
6266 SPOOL_REG_PRINTSHARENAME,
6267 REG_SZ,
6268 buffer.data,
6269 buffer.length);
6271 if (!force_update) {
6272 notify_printer_sharename(server_event_context(),
6273 msg_ctx,
6274 snum, printer->sharename ?
6275 printer->sharename : "");
6279 if (force_update || !strequal(printer->printername, old_printer->printername)) {
6280 const char *p;
6282 p = strrchr(printer->printername, '\\' );
6283 if (p != NULL) {
6284 p++;
6285 } else {
6286 p = printer->printername;
6289 push_reg_sz(mem_ctx, &buffer, p);
6290 winreg_set_printer_dataex(mem_ctx, b,
6291 printer->sharename,
6292 SPOOL_DSSPOOLER_KEY,
6293 SPOOL_REG_PRINTERNAME,
6294 REG_SZ,
6295 buffer.data,
6296 buffer.length);
6298 if (!force_update) {
6299 notify_printer_printername(server_event_context(),
6300 msg_ctx, snum, p ? p : "");
6304 if (force_update || !strequal(printer->portname, old_printer->portname)) {
6305 push_reg_sz(mem_ctx, &buffer, printer->portname);
6306 winreg_set_printer_dataex(mem_ctx, b,
6307 printer->sharename,
6308 SPOOL_DSSPOOLER_KEY,
6309 SPOOL_REG_PORTNAME,
6310 REG_SZ,
6311 buffer.data,
6312 buffer.length);
6314 if (!force_update) {
6315 notify_printer_port(server_event_context(),
6316 msg_ctx, snum, printer->portname ?
6317 printer->portname : "");
6321 if (force_update || !strequal(printer->location, old_printer->location)) {
6322 push_reg_sz(mem_ctx, &buffer, printer->location);
6323 winreg_set_printer_dataex(mem_ctx, b,
6324 printer->sharename,
6325 SPOOL_DSSPOOLER_KEY,
6326 SPOOL_REG_LOCATION,
6327 REG_SZ,
6328 buffer.data,
6329 buffer.length);
6331 if (!force_update) {
6332 notify_printer_location(server_event_context(),
6333 msg_ctx, snum,
6334 printer->location ?
6335 printer->location : "");
6339 if (force_update || !strequal(printer->sepfile, old_printer->sepfile)) {
6340 push_reg_sz(mem_ctx, &buffer, printer->sepfile);
6341 winreg_set_printer_dataex(mem_ctx, b,
6342 printer->sharename,
6343 SPOOL_DSSPOOLER_KEY,
6344 SPOOL_REG_PRINTSEPARATORFILE,
6345 REG_SZ,
6346 buffer.data,
6347 buffer.length);
6349 if (!force_update) {
6350 notify_printer_sepfile(server_event_context(),
6351 msg_ctx, snum,
6352 printer->sepfile ?
6353 printer->sepfile : "");
6357 if (force_update || printer->starttime != old_printer->starttime) {
6358 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6359 SIVAL(buffer.data, 0, printer->starttime);
6360 winreg_set_printer_dataex(mem_ctx, b,
6361 printer->sharename,
6362 SPOOL_DSSPOOLER_KEY,
6363 SPOOL_REG_PRINTSTARTTIME,
6364 REG_DWORD,
6365 buffer.data,
6366 buffer.length);
6369 if (force_update || printer->untiltime != old_printer->untiltime) {
6370 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6371 SIVAL(buffer.data, 0, printer->untiltime);
6372 winreg_set_printer_dataex(mem_ctx, b,
6373 printer->sharename,
6374 SPOOL_DSSPOOLER_KEY,
6375 SPOOL_REG_PRINTENDTIME,
6376 REG_DWORD,
6377 buffer.data,
6378 buffer.length);
6381 if (force_update || printer->priority != old_printer->priority) {
6382 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6383 SIVAL(buffer.data, 0, printer->priority);
6384 winreg_set_printer_dataex(mem_ctx, b,
6385 printer->sharename,
6386 SPOOL_DSSPOOLER_KEY,
6387 SPOOL_REG_PRIORITY,
6388 REG_DWORD,
6389 buffer.data,
6390 buffer.length);
6393 if (force_update || printer->attributes != old_printer->attributes) {
6394 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6395 SIVAL(buffer.data, 0, (printer->attributes &
6396 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6397 winreg_set_printer_dataex(mem_ctx, b,
6398 printer->sharename,
6399 SPOOL_DSSPOOLER_KEY,
6400 SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6401 REG_DWORD,
6402 buffer.data,
6403 buffer.length);
6405 switch (printer->attributes & 0x3) {
6406 case 0:
6407 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6408 break;
6409 case 1:
6410 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6411 break;
6412 case 2:
6413 spooling = SPOOL_REGVAL_PRINTDIRECT;
6414 break;
6415 default:
6416 spooling = "unknown";
6418 push_reg_sz(mem_ctx, &buffer, spooling);
6419 winreg_set_printer_dataex(mem_ctx, b,
6420 printer->sharename,
6421 SPOOL_DSSPOOLER_KEY,
6422 SPOOL_REG_PRINTSPOOLING,
6423 REG_SZ,
6424 buffer.data,
6425 buffer.length);
6428 push_reg_sz(mem_ctx, &buffer, global_myname());
6429 winreg_set_printer_dataex(mem_ctx, b,
6430 printer->sharename,
6431 SPOOL_DSSPOOLER_KEY,
6432 SPOOL_REG_SHORTSERVERNAME,
6433 REG_SZ,
6434 buffer.data,
6435 buffer.length);
6437 dnsdomname = get_mydnsfullname();
6438 if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6439 longname = talloc_strdup(mem_ctx, dnsdomname);
6440 } else {
6441 longname = talloc_strdup(mem_ctx, global_myname());
6443 if (longname == NULL) {
6444 result = WERR_NOMEM;
6445 goto done;
6448 push_reg_sz(mem_ctx, &buffer, longname);
6449 winreg_set_printer_dataex(mem_ctx, b,
6450 printer->sharename,
6451 SPOOL_DSSPOOLER_KEY,
6452 SPOOL_REG_SERVERNAME,
6453 REG_SZ,
6454 buffer.data,
6455 buffer.length);
6457 uncname = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6458 global_myname(), printer->sharename);
6459 push_reg_sz(mem_ctx, &buffer, uncname);
6460 winreg_set_printer_dataex(mem_ctx, b,
6461 printer->sharename,
6462 SPOOL_DSSPOOLER_KEY,
6463 SPOOL_REG_UNCNAME,
6464 REG_SZ,
6465 buffer.data,
6466 buffer.length);
6468 done:
6469 return result;
6472 /********************************************************************
6473 * Called by spoolss_api_setprinter
6474 * when updating a printer description.
6475 ********************************************************************/
6477 static WERROR update_printer(struct pipes_struct *p,
6478 struct policy_handle *handle,
6479 struct spoolss_SetPrinterInfoCtr *info_ctr,
6480 struct spoolss_DeviceMode *devmode)
6482 uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6483 struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6484 struct spoolss_PrinterInfo2 *old_printer;
6485 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6486 int snum;
6487 WERROR result = WERR_OK;
6488 TALLOC_CTX *tmp_ctx;
6489 struct dcerpc_binding_handle *b;
6491 DEBUG(8,("update_printer\n"));
6493 tmp_ctx = talloc_new(p->mem_ctx);
6494 if (tmp_ctx == NULL) {
6495 return WERR_NOMEM;
6498 if (!Printer) {
6499 result = WERR_BADFID;
6500 goto done;
6503 if (!get_printer_snum(p, handle, &snum, NULL)) {
6504 result = WERR_BADFID;
6505 goto done;
6508 result = winreg_printer_binding_handle(tmp_ctx,
6509 get_session_info_system(),
6510 p->msg_ctx,
6511 &b);
6512 if (!W_ERROR_IS_OK(result)) {
6513 goto done;
6516 result = winreg_get_printer(tmp_ctx, b,
6517 lp_const_servicename(snum),
6518 &old_printer);
6519 if (!W_ERROR_IS_OK(result)) {
6520 result = WERR_BADFID;
6521 goto done;
6524 /* Do sanity check on the requested changes for Samba */
6525 if (!check_printer_ok(tmp_ctx, printer, snum)) {
6526 result = WERR_INVALID_PARAM;
6527 goto done;
6530 /* FIXME!!! If the driver has changed we really should verify that
6531 it is installed before doing much else --jerry */
6533 /* Check calling user has permission to update printer description */
6534 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6535 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6536 result = WERR_ACCESS_DENIED;
6537 goto done;
6540 /* Call addprinter hook */
6541 /* Check changes to see if this is really needed */
6543 if (*lp_addprinter_cmd() &&
6544 (!strequal(printer->drivername, old_printer->drivername) ||
6545 !strequal(printer->comment, old_printer->comment) ||
6546 !strequal(printer->portname, old_printer->portname) ||
6547 !strequal(printer->location, old_printer->location)) )
6549 /* add_printer_hook() will call reload_services() */
6550 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6551 printer, p->client_id->addr,
6552 p->msg_ctx)) {
6553 result = WERR_ACCESS_DENIED;
6554 goto done;
6558 update_dsspooler(tmp_ctx,
6559 get_session_info_system(),
6560 p->msg_ctx,
6561 snum,
6562 printer,
6563 old_printer);
6565 printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6567 if (devmode == NULL) {
6568 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6570 result = winreg_update_printer(tmp_ctx, b,
6571 printer->sharename,
6572 printer_mask,
6573 printer,
6574 devmode,
6575 NULL);
6577 done:
6578 talloc_free(tmp_ctx);
6580 return result;
6583 /****************************************************************************
6584 ****************************************************************************/
6585 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6586 struct policy_handle *handle,
6587 struct spoolss_SetPrinterInfo7 *info7)
6589 #ifdef HAVE_ADS
6590 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6591 WERROR result;
6592 int snum;
6593 struct printer_handle *Printer;
6595 if ( lp_security() != SEC_ADS ) {
6596 return WERR_UNKNOWN_LEVEL;
6599 Printer = find_printer_index_by_hnd(p, handle);
6601 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6603 if (!Printer)
6604 return WERR_BADFID;
6606 if (!get_printer_snum(p, handle, &snum, NULL))
6607 return WERR_BADFID;
6609 result = winreg_get_printer_internal(p->mem_ctx,
6610 get_session_info_system(),
6611 p->msg_ctx,
6612 lp_servicename(snum),
6613 &pinfo2);
6614 if (!W_ERROR_IS_OK(result)) {
6615 return WERR_BADFID;
6618 nt_printer_publish(pinfo2,
6619 get_session_info_system(),
6620 p->msg_ctx,
6621 pinfo2,
6622 info7->action);
6624 TALLOC_FREE(pinfo2);
6625 return WERR_OK;
6626 #else
6627 return WERR_UNKNOWN_LEVEL;
6628 #endif
6631 /********************************************************************
6632 ********************************************************************/
6634 static WERROR update_printer_devmode(struct pipes_struct *p,
6635 struct policy_handle *handle,
6636 struct spoolss_DeviceMode *devmode)
6638 int snum;
6639 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6640 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6642 DEBUG(8,("update_printer_devmode\n"));
6644 if (!Printer) {
6645 return WERR_BADFID;
6648 if (!get_printer_snum(p, handle, &snum, NULL)) {
6649 return WERR_BADFID;
6652 /* Check calling user has permission to update printer description */
6653 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6654 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6655 return WERR_ACCESS_DENIED;
6658 return winreg_update_printer_internal(p->mem_ctx,
6659 get_session_info_system(),
6660 p->msg_ctx,
6661 lp_const_servicename(snum),
6662 info2_mask,
6663 NULL,
6664 devmode,
6665 NULL);
6669 /****************************************************************
6670 _spoolss_SetPrinter
6671 ****************************************************************/
6673 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6674 struct spoolss_SetPrinter *r)
6676 WERROR result;
6678 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6680 if (!Printer) {
6681 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6682 OUR_HANDLE(r->in.handle)));
6683 return WERR_BADFID;
6686 /* check the level */
6687 switch (r->in.info_ctr->level) {
6688 case 0:
6689 return control_printer(r->in.handle, r->in.command, p);
6690 case 2:
6691 result = update_printer(p, r->in.handle,
6692 r->in.info_ctr,
6693 r->in.devmode_ctr->devmode);
6694 if (!W_ERROR_IS_OK(result))
6695 return result;
6696 if (r->in.secdesc_ctr->sd)
6697 result = update_printer_sec(r->in.handle, p,
6698 r->in.secdesc_ctr);
6699 return result;
6700 case 3:
6701 return update_printer_sec(r->in.handle, p,
6702 r->in.secdesc_ctr);
6703 case 7:
6704 return publish_or_unpublish_printer(p, r->in.handle,
6705 r->in.info_ctr->info.info7);
6706 case 8:
6707 return update_printer_devmode(p, r->in.handle,
6708 r->in.devmode_ctr->devmode);
6709 default:
6710 return WERR_UNKNOWN_LEVEL;
6714 /****************************************************************
6715 _spoolss_FindClosePrinterNotify
6716 ****************************************************************/
6718 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
6719 struct spoolss_FindClosePrinterNotify *r)
6721 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6723 if (!Printer) {
6724 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6725 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6726 return WERR_BADFID;
6729 if (Printer->notify.cli_chan != NULL &&
6730 Printer->notify.cli_chan->active_connections > 0) {
6731 int snum = -1;
6733 if (Printer->printer_type == SPLHND_PRINTER) {
6734 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6735 return WERR_BADFID;
6739 srv_spoolss_replycloseprinter(snum, Printer);
6742 Printer->notify.flags=0;
6743 Printer->notify.options=0;
6744 Printer->notify.localmachine[0]='\0';
6745 Printer->notify.printerlocal=0;
6746 TALLOC_FREE(Printer->notify.option);
6748 return WERR_OK;
6751 /****************************************************************
6752 _spoolss_AddJob
6753 ****************************************************************/
6755 WERROR _spoolss_AddJob(struct pipes_struct *p,
6756 struct spoolss_AddJob *r)
6758 if (!r->in.buffer && (r->in.offered != 0)) {
6759 return WERR_INVALID_PARAM;
6762 /* this is what a NT server returns for AddJob. AddJob must fail on
6763 * non-local printers */
6765 if (r->in.level != 1) {
6766 return WERR_UNKNOWN_LEVEL;
6769 return WERR_INVALID_PARAM;
6772 /****************************************************************************
6773 fill_job_info1
6774 ****************************************************************************/
6776 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6777 struct spoolss_JobInfo1 *r,
6778 const print_queue_struct *queue,
6779 int position, int snum,
6780 struct spoolss_PrinterInfo2 *pinfo2)
6782 struct tm *t;
6784 t = gmtime(&queue->time);
6786 r->job_id = queue->job;
6788 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6789 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6790 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
6791 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6792 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6793 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6794 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6795 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6796 r->data_type = talloc_strdup(mem_ctx, "RAW");
6797 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6798 r->text_status = talloc_strdup(mem_ctx, "");
6799 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6801 r->status = nt_printj_status(queue->status);
6802 r->priority = queue->priority;
6803 r->position = position;
6804 r->total_pages = queue->page_count;
6805 r->pages_printed = 0; /* ??? */
6807 init_systemtime(&r->submitted, t);
6809 return WERR_OK;
6812 /****************************************************************************
6813 fill_job_info2
6814 ****************************************************************************/
6816 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6817 struct spoolss_JobInfo2 *r,
6818 const print_queue_struct *queue,
6819 int position, int snum,
6820 struct spoolss_PrinterInfo2 *pinfo2,
6821 struct spoolss_DeviceMode *devmode)
6823 struct tm *t;
6825 t = gmtime(&queue->time);
6827 r->job_id = queue->job;
6829 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6830 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6831 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
6832 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6833 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6834 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6835 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6836 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6837 r->notify_name = talloc_strdup(mem_ctx, queue->fs_user);
6838 W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6839 r->data_type = talloc_strdup(mem_ctx, "RAW");
6840 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6841 r->print_processor = talloc_strdup(mem_ctx, "winprint");
6842 W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6843 r->parameters = talloc_strdup(mem_ctx, "");
6844 W_ERROR_HAVE_NO_MEMORY(r->parameters);
6845 r->driver_name = talloc_strdup(mem_ctx, pinfo2->drivername);
6846 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6848 r->devmode = devmode;
6850 r->text_status = talloc_strdup(mem_ctx, "");
6851 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6853 r->secdesc = NULL;
6855 r->status = nt_printj_status(queue->status);
6856 r->priority = queue->priority;
6857 r->position = position;
6858 r->start_time = 0;
6859 r->until_time = 0;
6860 r->total_pages = queue->page_count;
6861 r->size = queue->size;
6862 init_systemtime(&r->submitted, t);
6863 r->time = 0;
6864 r->pages_printed = 0; /* ??? */
6866 return WERR_OK;
6869 /****************************************************************************
6870 fill_job_info3
6871 ****************************************************************************/
6873 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6874 struct spoolss_JobInfo3 *r,
6875 const print_queue_struct *queue,
6876 const print_queue_struct *next_queue,
6877 int position, int snum,
6878 struct spoolss_PrinterInfo2 *pinfo2)
6880 r->job_id = queue->job;
6881 r->next_job_id = 0;
6882 if (next_queue) {
6883 r->next_job_id = next_queue->job;
6885 r->reserved = 0;
6887 return WERR_OK;
6890 /****************************************************************************
6891 Enumjobs at level 1.
6892 ****************************************************************************/
6894 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6895 const print_queue_struct *queue,
6896 uint32_t num_queues, int snum,
6897 struct spoolss_PrinterInfo2 *pinfo2,
6898 union spoolss_JobInfo **info_p,
6899 uint32_t *count)
6901 union spoolss_JobInfo *info;
6902 int i;
6903 WERROR result = WERR_OK;
6905 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6906 W_ERROR_HAVE_NO_MEMORY(info);
6908 *count = num_queues;
6910 for (i=0; i<*count; i++) {
6911 result = fill_job_info1(info,
6912 &info[i].info1,
6913 &queue[i],
6915 snum,
6916 pinfo2);
6917 if (!W_ERROR_IS_OK(result)) {
6918 goto out;
6922 out:
6923 if (!W_ERROR_IS_OK(result)) {
6924 TALLOC_FREE(info);
6925 *count = 0;
6926 return result;
6929 *info_p = info;
6931 return WERR_OK;
6934 /****************************************************************************
6935 Enumjobs at level 2.
6936 ****************************************************************************/
6938 static WERROR enumjobs_level2(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 struct spoolss_DeviceMode *devmode;
6957 result = spoolss_create_default_devmode(info,
6958 pinfo2->printername,
6959 &devmode);
6960 if (!W_ERROR_IS_OK(result)) {
6961 DEBUG(3, ("Can't proceed w/o a devmode!"));
6962 goto out;
6965 result = fill_job_info2(info,
6966 &info[i].info2,
6967 &queue[i],
6969 snum,
6970 pinfo2,
6971 devmode);
6972 if (!W_ERROR_IS_OK(result)) {
6973 goto out;
6977 out:
6978 if (!W_ERROR_IS_OK(result)) {
6979 TALLOC_FREE(info);
6980 *count = 0;
6981 return result;
6984 *info_p = info;
6986 return WERR_OK;
6989 /****************************************************************************
6990 Enumjobs at level 3.
6991 ****************************************************************************/
6993 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
6994 const print_queue_struct *queue,
6995 uint32_t num_queues, int snum,
6996 struct spoolss_PrinterInfo2 *pinfo2,
6997 union spoolss_JobInfo **info_p,
6998 uint32_t *count)
7000 union spoolss_JobInfo *info;
7001 int i;
7002 WERROR result = WERR_OK;
7004 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
7005 W_ERROR_HAVE_NO_MEMORY(info);
7007 *count = num_queues;
7009 for (i=0; i<*count; i++) {
7010 const print_queue_struct *next_queue = NULL;
7012 if (i+1 < *count) {
7013 next_queue = &queue[i+1];
7016 result = fill_job_info3(info,
7017 &info[i].info3,
7018 &queue[i],
7019 next_queue,
7021 snum,
7022 pinfo2);
7023 if (!W_ERROR_IS_OK(result)) {
7024 goto out;
7028 out:
7029 if (!W_ERROR_IS_OK(result)) {
7030 TALLOC_FREE(info);
7031 *count = 0;
7032 return result;
7035 *info_p = info;
7037 return WERR_OK;
7040 /****************************************************************
7041 _spoolss_EnumJobs
7042 ****************************************************************/
7044 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7045 struct spoolss_EnumJobs *r)
7047 WERROR result;
7048 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7049 int snum;
7050 print_status_struct prt_status;
7051 print_queue_struct *queue = NULL;
7052 uint32_t count;
7054 /* that's an [in out] buffer */
7056 if (!r->in.buffer && (r->in.offered != 0)) {
7057 return WERR_INVALID_PARAM;
7060 DEBUG(4,("_spoolss_EnumJobs\n"));
7062 *r->out.needed = 0;
7063 *r->out.count = 0;
7064 *r->out.info = NULL;
7066 /* lookup the printer snum and tdb entry */
7068 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7069 return WERR_BADFID;
7072 result = winreg_get_printer_internal(p->mem_ctx,
7073 get_session_info_system(),
7074 p->msg_ctx,
7075 lp_const_servicename(snum),
7076 &pinfo2);
7077 if (!W_ERROR_IS_OK(result)) {
7078 return result;
7081 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7082 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7083 count, prt_status.status, prt_status.message));
7085 if (count == 0) {
7086 SAFE_FREE(queue);
7087 TALLOC_FREE(pinfo2);
7088 return WERR_OK;
7091 switch (r->in.level) {
7092 case 1:
7093 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7094 pinfo2, r->out.info, r->out.count);
7095 break;
7096 case 2:
7097 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7098 pinfo2, r->out.info, r->out.count);
7099 break;
7100 case 3:
7101 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7102 pinfo2, r->out.info, r->out.count);
7103 break;
7104 default:
7105 result = WERR_UNKNOWN_LEVEL;
7106 break;
7109 SAFE_FREE(queue);
7110 TALLOC_FREE(pinfo2);
7112 if (!W_ERROR_IS_OK(result)) {
7113 return result;
7116 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7117 spoolss_EnumJobs,
7118 *r->out.info, r->in.level,
7119 *r->out.count);
7120 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7121 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7123 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7126 /****************************************************************
7127 _spoolss_ScheduleJob
7128 ****************************************************************/
7130 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7131 struct spoolss_ScheduleJob *r)
7133 return WERR_OK;
7136 /****************************************************************
7137 ****************************************************************/
7139 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7140 struct messaging_context *msg_ctx,
7141 const char *printer_name,
7142 uint32_t job_id,
7143 struct spoolss_SetJobInfo1 *r)
7145 char *old_doc_name;
7147 if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7148 return WERR_BADFID;
7151 if (strequal(old_doc_name, r->document_name)) {
7152 return WERR_OK;
7155 if (!print_job_set_name(server_event_context(), msg_ctx,
7156 printer_name, job_id, r->document_name)) {
7157 return WERR_BADFID;
7160 return WERR_OK;
7163 /****************************************************************
7164 _spoolss_SetJob
7165 ****************************************************************/
7167 WERROR _spoolss_SetJob(struct pipes_struct *p,
7168 struct spoolss_SetJob *r)
7170 const struct auth_serversupplied_info *session_info = p->session_info;
7171 int snum;
7172 WERROR errcode = WERR_BADFUNC;
7174 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7175 return WERR_BADFID;
7178 if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7179 return WERR_INVALID_PRINTER_NAME;
7182 switch (r->in.command) {
7183 case SPOOLSS_JOB_CONTROL_CANCEL:
7184 case SPOOLSS_JOB_CONTROL_DELETE:
7185 errcode = print_job_delete(session_info, p->msg_ctx,
7186 snum, r->in.job_id);
7187 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7188 errcode = WERR_OK;
7190 break;
7191 case SPOOLSS_JOB_CONTROL_PAUSE:
7192 if (print_job_pause(session_info, p->msg_ctx,
7193 snum, r->in.job_id, &errcode)) {
7194 errcode = WERR_OK;
7196 break;
7197 case SPOOLSS_JOB_CONTROL_RESTART:
7198 case SPOOLSS_JOB_CONTROL_RESUME:
7199 if (print_job_resume(session_info, p->msg_ctx,
7200 snum, r->in.job_id, &errcode)) {
7201 errcode = WERR_OK;
7203 break;
7204 case 0:
7205 errcode = WERR_OK;
7206 break;
7207 default:
7208 return WERR_UNKNOWN_LEVEL;
7211 if (!W_ERROR_IS_OK(errcode)) {
7212 return errcode;
7215 if (r->in.ctr == NULL) {
7216 return errcode;
7219 switch (r->in.ctr->level) {
7220 case 1:
7221 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7222 lp_const_servicename(snum),
7223 r->in.job_id,
7224 r->in.ctr->info.info1);
7225 break;
7226 case 2:
7227 case 3:
7228 case 4:
7229 default:
7230 return WERR_UNKNOWN_LEVEL;
7233 return errcode;
7236 /****************************************************************************
7237 Enumerates all printer drivers by level and architecture.
7238 ****************************************************************************/
7240 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7241 const struct auth_serversupplied_info *session_info,
7242 struct messaging_context *msg_ctx,
7243 const char *servername,
7244 const char *architecture,
7245 uint32_t level,
7246 union spoolss_DriverInfo **info_p,
7247 uint32_t *count_p)
7249 int i;
7250 uint32_t version;
7251 struct spoolss_DriverInfo8 *driver;
7252 union spoolss_DriverInfo *info = NULL;
7253 uint32_t count = 0;
7254 WERROR result = WERR_OK;
7255 uint32_t num_drivers;
7256 const char **drivers;
7257 struct dcerpc_binding_handle *b;
7259 *count_p = 0;
7260 *info_p = NULL;
7262 result = winreg_printer_binding_handle(mem_ctx,
7263 session_info,
7264 msg_ctx,
7265 &b);
7266 if (!W_ERROR_IS_OK(result)) {
7267 goto out;
7270 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7271 result = winreg_get_driver_list(mem_ctx, b,
7272 architecture, version,
7273 &num_drivers, &drivers);
7274 if (!W_ERROR_IS_OK(result)) {
7275 goto out;
7277 DEBUG(4, ("we have:[%d] drivers in environment"
7278 " [%s] and version [%d]\n",
7279 num_drivers, architecture, version));
7281 if (num_drivers != 0) {
7282 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
7283 union spoolss_DriverInfo,
7284 count + num_drivers);
7285 if (!info) {
7286 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7287 "failed to enlarge driver info buffer!\n"));
7288 result = WERR_NOMEM;
7289 goto out;
7293 for (i = 0; i < num_drivers; i++) {
7294 DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7296 result = winreg_get_driver(mem_ctx, b,
7297 architecture, drivers[i],
7298 version, &driver);
7299 if (!W_ERROR_IS_OK(result)) {
7300 goto out;
7303 switch (level) {
7304 case 1:
7305 result = fill_printer_driver_info1(info, &info[count+i].info1,
7306 driver, servername);
7307 break;
7308 case 2:
7309 result = fill_printer_driver_info2(info, &info[count+i].info2,
7310 driver, servername);
7311 break;
7312 case 3:
7313 result = fill_printer_driver_info3(info, &info[count+i].info3,
7314 driver, servername);
7315 break;
7316 case 4:
7317 result = fill_printer_driver_info4(info, &info[count+i].info4,
7318 driver, servername);
7319 break;
7320 case 5:
7321 result = fill_printer_driver_info5(info, &info[count+i].info5,
7322 driver, servername);
7323 break;
7324 case 6:
7325 result = fill_printer_driver_info6(info, &info[count+i].info6,
7326 driver, servername);
7327 break;
7328 case 8:
7329 result = fill_printer_driver_info8(info, &info[count+i].info8,
7330 driver, servername);
7331 break;
7332 default:
7333 result = WERR_UNKNOWN_LEVEL;
7334 break;
7337 TALLOC_FREE(driver);
7339 if (!W_ERROR_IS_OK(result)) {
7340 goto out;
7344 count += num_drivers;
7345 TALLOC_FREE(drivers);
7348 out:
7349 TALLOC_FREE(drivers);
7351 if (!W_ERROR_IS_OK(result)) {
7352 TALLOC_FREE(info);
7353 return result;
7356 *info_p = info;
7357 *count_p = count;
7359 return WERR_OK;
7362 /****************************************************************************
7363 Enumerates all printer drivers by level.
7364 ****************************************************************************/
7366 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7367 const struct auth_serversupplied_info *session_info,
7368 struct messaging_context *msg_ctx,
7369 const char *servername,
7370 const char *architecture,
7371 uint32_t level,
7372 union spoolss_DriverInfo **info_p,
7373 uint32_t *count_p)
7375 uint32_t a,i;
7376 WERROR result = WERR_OK;
7378 if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7380 for (a=0; archi_table[a].long_archi != NULL; a++) {
7382 union spoolss_DriverInfo *info = NULL;
7383 uint32_t count = 0;
7385 result = enumprinterdrivers_level_by_architecture(mem_ctx,
7386 session_info,
7387 msg_ctx,
7388 servername,
7389 archi_table[a].long_archi,
7390 level,
7391 &info,
7392 &count);
7393 if (!W_ERROR_IS_OK(result)) {
7394 continue;
7397 for (i=0; i < count; i++) {
7398 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7399 info[i], info_p, count_p);
7403 return result;
7406 return enumprinterdrivers_level_by_architecture(mem_ctx,
7407 session_info,
7408 msg_ctx,
7409 servername,
7410 architecture,
7411 level,
7412 info_p,
7413 count_p);
7416 /****************************************************************
7417 _spoolss_EnumPrinterDrivers
7418 ****************************************************************/
7420 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7421 struct spoolss_EnumPrinterDrivers *r)
7423 const char *cservername;
7424 WERROR result;
7426 /* that's an [in out] buffer */
7428 if (!r->in.buffer && (r->in.offered != 0)) {
7429 return WERR_INVALID_PARAM;
7432 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7434 *r->out.needed = 0;
7435 *r->out.count = 0;
7436 *r->out.info = NULL;
7438 cservername = canon_servername(r->in.server);
7440 if (!is_myname_or_ipaddr(cservername)) {
7441 return WERR_UNKNOWN_PRINTER_DRIVER;
7444 result = enumprinterdrivers_level(p->mem_ctx,
7445 get_session_info_system(),
7446 p->msg_ctx,
7447 cservername,
7448 r->in.environment,
7449 r->in.level,
7450 r->out.info,
7451 r->out.count);
7452 if (!W_ERROR_IS_OK(result)) {
7453 return result;
7456 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7457 spoolss_EnumPrinterDrivers,
7458 *r->out.info, r->in.level,
7459 *r->out.count);
7460 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7461 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7463 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7466 /****************************************************************
7467 _spoolss_EnumForms
7468 ****************************************************************/
7470 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7471 struct spoolss_EnumForms *r)
7473 WERROR result;
7475 *r->out.count = 0;
7476 *r->out.needed = 0;
7477 *r->out.info = NULL;
7479 /* that's an [in out] buffer */
7481 if (!r->in.buffer && (r->in.offered != 0) ) {
7482 return WERR_INVALID_PARAM;
7485 DEBUG(4,("_spoolss_EnumForms\n"));
7486 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7487 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7489 switch (r->in.level) {
7490 case 1:
7491 result = winreg_printer_enumforms1_internal(p->mem_ctx,
7492 get_session_info_system(),
7493 p->msg_ctx,
7494 r->out.count,
7495 r->out.info);
7496 break;
7497 default:
7498 result = WERR_UNKNOWN_LEVEL;
7499 break;
7502 if (!W_ERROR_IS_OK(result)) {
7503 return result;
7506 if (*r->out.count == 0) {
7507 return WERR_NO_MORE_ITEMS;
7510 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7511 spoolss_EnumForms,
7512 *r->out.info, r->in.level,
7513 *r->out.count);
7514 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7515 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7517 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7520 /****************************************************************
7521 _spoolss_GetForm
7522 ****************************************************************/
7524 WERROR _spoolss_GetForm(struct pipes_struct *p,
7525 struct spoolss_GetForm *r)
7527 WERROR result;
7529 /* that's an [in out] buffer */
7531 if (!r->in.buffer && (r->in.offered != 0)) {
7532 return WERR_INVALID_PARAM;
7535 DEBUG(4,("_spoolss_GetForm\n"));
7536 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7537 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7539 switch (r->in.level) {
7540 case 1:
7541 result = winreg_printer_getform1_internal(p->mem_ctx,
7542 get_session_info_system(),
7543 p->msg_ctx,
7544 r->in.form_name,
7545 &r->out.info->info1);
7546 break;
7547 default:
7548 result = WERR_UNKNOWN_LEVEL;
7549 break;
7552 if (!W_ERROR_IS_OK(result)) {
7553 TALLOC_FREE(r->out.info);
7554 return result;
7557 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
7558 r->out.info, r->in.level);
7559 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7561 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7564 /****************************************************************************
7565 ****************************************************************************/
7567 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7568 struct spoolss_PortInfo1 *r,
7569 const char *name)
7571 r->port_name = talloc_strdup(mem_ctx, name);
7572 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7574 return WERR_OK;
7577 /****************************************************************************
7578 TODO: This probably needs distinguish between TCP/IP and Local ports
7579 somehow.
7580 ****************************************************************************/
7582 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7583 struct spoolss_PortInfo2 *r,
7584 const char *name)
7586 r->port_name = talloc_strdup(mem_ctx, name);
7587 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7589 r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7590 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7592 r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7593 W_ERROR_HAVE_NO_MEMORY(r->description);
7595 r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7596 r->reserved = 0;
7598 return WERR_OK;
7602 /****************************************************************************
7603 wrapper around the enumer ports command
7604 ****************************************************************************/
7606 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7608 char *cmd = lp_enumports_cmd();
7609 char **qlines = NULL;
7610 char *command = NULL;
7611 int numlines;
7612 int ret;
7613 int fd;
7615 *count = 0;
7616 *lines = NULL;
7618 /* if no hook then just fill in the default port */
7620 if ( !*cmd ) {
7621 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7622 return WERR_NOMEM;
7624 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7625 TALLOC_FREE(qlines);
7626 return WERR_NOMEM;
7628 qlines[1] = NULL;
7629 numlines = 1;
7631 else {
7632 /* we have a valid enumport command */
7634 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7635 if (!command) {
7636 return WERR_NOMEM;
7639 DEBUG(10,("Running [%s]\n", command));
7640 ret = smbrun(command, &fd);
7641 DEBUG(10,("Returned [%d]\n", ret));
7642 TALLOC_FREE(command);
7643 if (ret != 0) {
7644 if (fd != -1) {
7645 close(fd);
7647 return WERR_ACCESS_DENIED;
7650 numlines = 0;
7651 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7652 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7653 close(fd);
7656 *count = numlines;
7657 *lines = qlines;
7659 return WERR_OK;
7662 /****************************************************************************
7663 enumports level 1.
7664 ****************************************************************************/
7666 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7667 union spoolss_PortInfo **info_p,
7668 uint32_t *count)
7670 union spoolss_PortInfo *info = NULL;
7671 int i=0;
7672 WERROR result = WERR_OK;
7673 char **qlines = NULL;
7674 int numlines = 0;
7676 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7677 if (!W_ERROR_IS_OK(result)) {
7678 goto out;
7681 if (numlines) {
7682 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7683 if (!info) {
7684 DEBUG(10,("Returning WERR_NOMEM\n"));
7685 result = WERR_NOMEM;
7686 goto out;
7689 for (i=0; i<numlines; i++) {
7690 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7691 result = fill_port_1(info, &info[i].info1, qlines[i]);
7692 if (!W_ERROR_IS_OK(result)) {
7693 goto out;
7697 TALLOC_FREE(qlines);
7699 out:
7700 if (!W_ERROR_IS_OK(result)) {
7701 TALLOC_FREE(info);
7702 TALLOC_FREE(qlines);
7703 *count = 0;
7704 *info_p = NULL;
7705 return result;
7708 *info_p = info;
7709 *count = numlines;
7711 return WERR_OK;
7714 /****************************************************************************
7715 enumports level 2.
7716 ****************************************************************************/
7718 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7719 union spoolss_PortInfo **info_p,
7720 uint32_t *count)
7722 union spoolss_PortInfo *info = NULL;
7723 int i=0;
7724 WERROR result = WERR_OK;
7725 char **qlines = NULL;
7726 int numlines = 0;
7728 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7729 if (!W_ERROR_IS_OK(result)) {
7730 goto out;
7733 if (numlines) {
7734 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7735 if (!info) {
7736 DEBUG(10,("Returning WERR_NOMEM\n"));
7737 result = WERR_NOMEM;
7738 goto out;
7741 for (i=0; i<numlines; i++) {
7742 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7743 result = fill_port_2(info, &info[i].info2, qlines[i]);
7744 if (!W_ERROR_IS_OK(result)) {
7745 goto out;
7749 TALLOC_FREE(qlines);
7751 out:
7752 if (!W_ERROR_IS_OK(result)) {
7753 TALLOC_FREE(info);
7754 TALLOC_FREE(qlines);
7755 *count = 0;
7756 *info_p = NULL;
7757 return result;
7760 *info_p = info;
7761 *count = numlines;
7763 return WERR_OK;
7766 /****************************************************************
7767 _spoolss_EnumPorts
7768 ****************************************************************/
7770 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
7771 struct spoolss_EnumPorts *r)
7773 WERROR result;
7775 /* that's an [in out] buffer */
7777 if (!r->in.buffer && (r->in.offered != 0)) {
7778 return WERR_INVALID_PARAM;
7781 DEBUG(4,("_spoolss_EnumPorts\n"));
7783 *r->out.count = 0;
7784 *r->out.needed = 0;
7785 *r->out.info = NULL;
7787 switch (r->in.level) {
7788 case 1:
7789 result = enumports_level_1(p->mem_ctx, r->out.info,
7790 r->out.count);
7791 break;
7792 case 2:
7793 result = enumports_level_2(p->mem_ctx, r->out.info,
7794 r->out.count);
7795 break;
7796 default:
7797 return WERR_UNKNOWN_LEVEL;
7800 if (!W_ERROR_IS_OK(result)) {
7801 return result;
7804 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7805 spoolss_EnumPorts,
7806 *r->out.info, r->in.level,
7807 *r->out.count);
7808 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7809 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7811 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7814 /****************************************************************************
7815 ****************************************************************************/
7817 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
7818 const char *server,
7819 struct spoolss_SetPrinterInfoCtr *info_ctr,
7820 struct spoolss_DeviceMode *devmode,
7821 struct security_descriptor *secdesc,
7822 struct spoolss_UserLevelCtr *user_ctr,
7823 struct policy_handle *handle)
7825 struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
7826 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
7827 int snum;
7828 WERROR err = WERR_OK;
7830 /* samba does not have a concept of local, non-shared printers yet, so
7831 * make sure we always setup sharename - gd */
7832 if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
7833 (info2->printername != NULL && info2->printername[0] != '\0')) {
7834 DEBUG(5, ("spoolss_addprinterex_level_2: "
7835 "no sharename has been set, setting printername %s as sharename\n",
7836 info2->printername));
7837 info2->sharename = info2->printername;
7840 /* check to see if the printer already exists */
7841 if ((snum = print_queue_snum(info2->sharename)) != -1) {
7842 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7843 info2->sharename));
7844 return WERR_PRINTER_ALREADY_EXISTS;
7847 if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7848 if ((snum = print_queue_snum(info2->printername)) != -1) {
7849 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7850 info2->printername));
7851 return WERR_PRINTER_ALREADY_EXISTS;
7855 /* validate printer info struct */
7856 if (!info2->printername || strlen(info2->printername) == 0) {
7857 return WERR_INVALID_PRINTER_NAME;
7859 if (!info2->portname || strlen(info2->portname) == 0) {
7860 return WERR_UNKNOWN_PORT;
7862 if (!info2->drivername || strlen(info2->drivername) == 0) {
7863 return WERR_UNKNOWN_PRINTER_DRIVER;
7865 if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
7866 return WERR_UNKNOWN_PRINTPROCESSOR;
7869 /* FIXME!!! smbd should check to see if the driver is installed before
7870 trying to add a printer like this --jerry */
7872 if (*lp_addprinter_cmd() ) {
7873 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
7874 info2, p->client_id->addr,
7875 p->msg_ctx) ) {
7876 return WERR_ACCESS_DENIED;
7878 } else {
7879 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
7880 "smb.conf parameter \"addprinter command\" is defined. This "
7881 "parameter must exist for this call to succeed\n",
7882 info2->sharename ));
7885 if ((snum = print_queue_snum(info2->sharename)) == -1) {
7886 return WERR_ACCESS_DENIED;
7889 /* you must be a printer admin to add a new printer */
7890 if (!print_access_check(p->session_info,
7891 p->msg_ctx,
7892 snum,
7893 PRINTER_ACCESS_ADMINISTER)) {
7894 return WERR_ACCESS_DENIED;
7898 * Do sanity check on the requested changes for Samba.
7901 if (!check_printer_ok(p->mem_ctx, info2, snum)) {
7902 return WERR_INVALID_PARAM;
7905 if (devmode == NULL) {
7906 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
7909 update_dsspooler(p->mem_ctx,
7910 get_session_info_system(),
7911 p->msg_ctx,
7913 info2,
7914 NULL);
7916 err = winreg_update_printer_internal(p->mem_ctx,
7917 get_session_info_system(),
7918 p->msg_ctx,
7919 info2->sharename,
7920 info2_mask,
7921 info2,
7922 devmode,
7923 secdesc);
7924 if (!W_ERROR_IS_OK(err)) {
7925 return err;
7928 err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
7929 if (!W_ERROR_IS_OK(err)) {
7930 /* Handle open failed - remove addition. */
7931 ZERO_STRUCTP(handle);
7932 return err;
7935 return WERR_OK;
7938 /****************************************************************
7939 _spoolss_AddPrinterEx
7940 ****************************************************************/
7942 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
7943 struct spoolss_AddPrinterEx *r)
7945 switch (r->in.info_ctr->level) {
7946 case 1:
7947 /* we don't handle yet */
7948 /* but I know what to do ... */
7949 return WERR_UNKNOWN_LEVEL;
7950 case 2:
7951 return spoolss_addprinterex_level_2(p, r->in.server,
7952 r->in.info_ctr,
7953 r->in.devmode_ctr->devmode,
7954 r->in.secdesc_ctr->sd,
7955 r->in.userlevel_ctr,
7956 r->out.handle);
7957 default:
7958 return WERR_UNKNOWN_LEVEL;
7962 /****************************************************************
7963 _spoolss_AddPrinter
7964 ****************************************************************/
7966 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
7967 struct spoolss_AddPrinter *r)
7969 struct spoolss_AddPrinterEx a;
7970 struct spoolss_UserLevelCtr userlevel_ctr;
7972 ZERO_STRUCT(userlevel_ctr);
7974 userlevel_ctr.level = 1;
7976 a.in.server = r->in.server;
7977 a.in.info_ctr = r->in.info_ctr;
7978 a.in.devmode_ctr = r->in.devmode_ctr;
7979 a.in.secdesc_ctr = r->in.secdesc_ctr;
7980 a.in.userlevel_ctr = &userlevel_ctr;
7981 a.out.handle = r->out.handle;
7983 return _spoolss_AddPrinterEx(p, &a);
7986 /****************************************************************
7987 _spoolss_AddPrinterDriverEx
7988 ****************************************************************/
7990 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
7991 struct spoolss_AddPrinterDriverEx *r)
7993 WERROR err = WERR_OK;
7994 const char *driver_name = NULL;
7995 uint32_t version;
7996 const char *fn;
7998 switch (p->opnum) {
7999 case NDR_SPOOLSS_ADDPRINTERDRIVER:
8000 fn = "_spoolss_AddPrinterDriver";
8001 break;
8002 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
8003 fn = "_spoolss_AddPrinterDriverEx";
8004 break;
8005 default:
8006 return WERR_INVALID_PARAM;
8010 * we only support the semantics of AddPrinterDriver()
8011 * i.e. only copy files that are newer than existing ones
8014 if (r->in.flags == 0) {
8015 return WERR_INVALID_PARAM;
8018 if (r->in.flags != APD_COPY_NEW_FILES) {
8019 return WERR_ACCESS_DENIED;
8022 /* FIXME */
8023 if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
8024 /* Clever hack from Martin Zielinski <mz@seh.de>
8025 * to allow downgrade from level 8 (Vista).
8027 DEBUG(0,("%s: level %d not yet implemented\n", fn,
8028 r->in.info_ctr->level));
8029 return WERR_UNKNOWN_LEVEL;
8032 DEBUG(5,("Cleaning driver's information\n"));
8033 err = clean_up_driver_struct(p->mem_ctx, p->session_info, r->in.info_ctr);
8034 if (!W_ERROR_IS_OK(err))
8035 goto done;
8037 DEBUG(5,("Moving driver to final destination\n"));
8038 err = move_driver_to_download_area(p->session_info, r->in.info_ctr);
8039 if (!W_ERROR_IS_OK(err)) {
8040 goto done;
8043 err = winreg_add_driver_internal(p->mem_ctx,
8044 get_session_info_system(),
8045 p->msg_ctx,
8046 r->in.info_ctr,
8047 &driver_name,
8048 &version);
8049 if (!W_ERROR_IS_OK(err)) {
8050 goto done;
8054 * I think this is where he DrvUpgradePrinter() hook would be
8055 * be called in a driver's interface DLL on a Windows NT 4.0/2k
8056 * server. Right now, we just need to send ourselves a message
8057 * to update each printer bound to this driver. --jerry
8060 if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8061 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8062 fn, driver_name));
8065 done:
8066 return err;
8069 /****************************************************************
8070 _spoolss_AddPrinterDriver
8071 ****************************************************************/
8073 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8074 struct spoolss_AddPrinterDriver *r)
8076 struct spoolss_AddPrinterDriverEx a;
8078 switch (r->in.info_ctr->level) {
8079 case 2:
8080 case 3:
8081 case 4:
8082 case 5:
8083 break;
8084 default:
8085 return WERR_UNKNOWN_LEVEL;
8088 a.in.servername = r->in.servername;
8089 a.in.info_ctr = r->in.info_ctr;
8090 a.in.flags = APD_COPY_NEW_FILES;
8092 return _spoolss_AddPrinterDriverEx(p, &a);
8095 /****************************************************************************
8096 ****************************************************************************/
8098 struct _spoolss_paths {
8099 int type;
8100 const char *share;
8101 const char *dir;
8104 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8106 static const struct _spoolss_paths spoolss_paths[]= {
8107 { SPOOLSS_DRIVER_PATH, "print$", "DRIVERS" },
8108 { SPOOLSS_PRTPROCS_PATH, "prnproc$", "PRTPROCS" }
8111 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8112 const char *servername,
8113 const char *environment,
8114 int component,
8115 char **path)
8117 const char *pservername = NULL;
8118 const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
8119 const char *short_archi;
8121 *path = NULL;
8123 /* environment may be empty */
8124 if (environment && strlen(environment)) {
8125 long_archi = environment;
8128 /* servername may be empty */
8129 if (servername && strlen(servername)) {
8130 pservername = canon_servername(servername);
8132 if (!is_myname_or_ipaddr(pservername)) {
8133 return WERR_INVALID_PARAM;
8137 if (!(short_archi = get_short_archi(long_archi))) {
8138 return WERR_INVALID_ENVIRONMENT;
8141 switch (component) {
8142 case SPOOLSS_PRTPROCS_PATH:
8143 case SPOOLSS_DRIVER_PATH:
8144 if (pservername) {
8145 *path = talloc_asprintf(mem_ctx,
8146 "\\\\%s\\%s\\%s",
8147 pservername,
8148 spoolss_paths[component].share,
8149 short_archi);
8150 } else {
8151 *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8152 SPOOLSS_DEFAULT_SERVER_PATH,
8153 spoolss_paths[component].dir,
8154 short_archi);
8156 break;
8157 default:
8158 return WERR_INVALID_PARAM;
8161 if (!*path) {
8162 return WERR_NOMEM;
8165 return WERR_OK;
8168 /****************************************************************************
8169 ****************************************************************************/
8171 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8172 const char *servername,
8173 const char *environment,
8174 struct spoolss_DriverDirectoryInfo1 *r)
8176 WERROR werr;
8177 char *path = NULL;
8179 werr = compose_spoolss_server_path(mem_ctx,
8180 servername,
8181 environment,
8182 SPOOLSS_DRIVER_PATH,
8183 &path);
8184 if (!W_ERROR_IS_OK(werr)) {
8185 return werr;
8188 DEBUG(4,("printer driver directory: [%s]\n", path));
8190 r->directory_name = path;
8192 return WERR_OK;
8195 /****************************************************************
8196 _spoolss_GetPrinterDriverDirectory
8197 ****************************************************************/
8199 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8200 struct spoolss_GetPrinterDriverDirectory *r)
8202 WERROR werror;
8204 /* that's an [in out] buffer */
8206 if (!r->in.buffer && (r->in.offered != 0)) {
8207 return WERR_INVALID_PARAM;
8210 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8211 r->in.level));
8213 *r->out.needed = 0;
8215 /* r->in.level is ignored */
8217 werror = getprinterdriverdir_level_1(p->mem_ctx,
8218 r->in.server,
8219 r->in.environment,
8220 &r->out.info->info1);
8221 if (!W_ERROR_IS_OK(werror)) {
8222 TALLOC_FREE(r->out.info);
8223 return werror;
8226 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8227 r->out.info, r->in.level);
8228 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8230 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8233 /****************************************************************
8234 _spoolss_EnumPrinterData
8235 ****************************************************************/
8237 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8238 struct spoolss_EnumPrinterData *r)
8240 WERROR result;
8241 struct spoolss_EnumPrinterDataEx r2;
8242 uint32_t count;
8243 struct spoolss_PrinterEnumValues *info, *val = NULL;
8244 uint32_t needed;
8246 r2.in.handle = r->in.handle;
8247 r2.in.key_name = "PrinterDriverData";
8248 r2.in.offered = 0;
8249 r2.out.count = &count;
8250 r2.out.info = &info;
8251 r2.out.needed = &needed;
8253 result = _spoolss_EnumPrinterDataEx(p, &r2);
8254 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8255 r2.in.offered = needed;
8256 result = _spoolss_EnumPrinterDataEx(p, &r2);
8258 if (!W_ERROR_IS_OK(result)) {
8259 return result;
8263 * The NT machine wants to know the biggest size of value and data
8265 * cf: MSDN EnumPrinterData remark section
8268 if (!r->in.value_offered && !r->in.data_offered) {
8269 uint32_t biggest_valuesize = 0;
8270 uint32_t biggest_datasize = 0;
8271 int i, name_length;
8273 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8275 for (i=0; i<count; i++) {
8277 name_length = strlen(info[i].value_name);
8278 if (strlen(info[i].value_name) > biggest_valuesize) {
8279 biggest_valuesize = name_length;
8282 if (info[i].data_length > biggest_datasize) {
8283 biggest_datasize = info[i].data_length;
8286 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8287 biggest_datasize));
8290 /* the value is an UNICODE string but real_value_size is the length
8291 in bytes including the trailing 0 */
8293 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8294 *r->out.data_needed = biggest_datasize;
8296 DEBUG(6,("final values: [%d], [%d]\n",
8297 *r->out.value_needed, *r->out.data_needed));
8299 return WERR_OK;
8302 if (r->in.enum_index < count) {
8303 val = &info[r->in.enum_index];
8306 if (val == NULL) {
8307 /* out_value should default to "" or else NT4 has
8308 problems unmarshalling the response */
8310 if (r->in.value_offered) {
8311 *r->out.value_needed = 1;
8312 r->out.value_name = talloc_strdup(r, "");
8313 if (!r->out.value_name) {
8314 return WERR_NOMEM;
8316 } else {
8317 r->out.value_name = NULL;
8318 *r->out.value_needed = 0;
8321 /* the data is counted in bytes */
8323 *r->out.data_needed = r->in.data_offered;
8325 result = WERR_NO_MORE_ITEMS;
8326 } else {
8328 * the value is:
8329 * - counted in bytes in the request
8330 * - counted in UNICODE chars in the max reply
8331 * - counted in bytes in the real size
8333 * take a pause *before* coding not *during* coding
8336 /* name */
8337 if (r->in.value_offered) {
8338 r->out.value_name = talloc_strdup(r, val->value_name);
8339 if (!r->out.value_name) {
8340 return WERR_NOMEM;
8342 *r->out.value_needed = val->value_name_len;
8343 } else {
8344 r->out.value_name = NULL;
8345 *r->out.value_needed = 0;
8348 /* type */
8350 *r->out.type = val->type;
8352 /* data - counted in bytes */
8355 * See the section "Dynamically Typed Query Parameters"
8356 * in MS-RPRN.
8359 if (r->out.data && val->data && val->data->data &&
8360 val->data_length && r->in.data_offered) {
8361 memcpy(r->out.data, val->data->data,
8362 MIN(val->data_length,r->in.data_offered));
8365 *r->out.data_needed = val->data_length;
8367 result = WERR_OK;
8370 return result;
8373 /****************************************************************
8374 _spoolss_SetPrinterData
8375 ****************************************************************/
8377 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8378 struct spoolss_SetPrinterData *r)
8380 struct spoolss_SetPrinterDataEx r2;
8382 r2.in.handle = r->in.handle;
8383 r2.in.key_name = "PrinterDriverData";
8384 r2.in.value_name = r->in.value_name;
8385 r2.in.type = r->in.type;
8386 r2.in.data = r->in.data;
8387 r2.in.offered = r->in.offered;
8389 return _spoolss_SetPrinterDataEx(p, &r2);
8392 /****************************************************************
8393 _spoolss_ResetPrinter
8394 ****************************************************************/
8396 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8397 struct spoolss_ResetPrinter *r)
8399 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8400 int snum;
8402 DEBUG(5,("_spoolss_ResetPrinter\n"));
8405 * All we do is to check to see if the handle and queue is valid.
8406 * This call really doesn't mean anything to us because we only
8407 * support RAW printing. --jerry
8410 if (!Printer) {
8411 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8412 OUR_HANDLE(r->in.handle)));
8413 return WERR_BADFID;
8416 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8417 return WERR_BADFID;
8420 /* blindly return success */
8421 return WERR_OK;
8424 /****************************************************************
8425 _spoolss_DeletePrinterData
8426 ****************************************************************/
8428 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8429 struct spoolss_DeletePrinterData *r)
8431 struct spoolss_DeletePrinterDataEx r2;
8433 r2.in.handle = r->in.handle;
8434 r2.in.key_name = "PrinterDriverData";
8435 r2.in.value_name = r->in.value_name;
8437 return _spoolss_DeletePrinterDataEx(p, &r2);
8440 /****************************************************************
8441 _spoolss_AddForm
8442 ****************************************************************/
8444 WERROR _spoolss_AddForm(struct pipes_struct *p,
8445 struct spoolss_AddForm *r)
8447 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8448 int snum = -1;
8449 WERROR status = WERR_OK;
8450 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8451 struct dcerpc_binding_handle *b;
8453 DEBUG(5,("_spoolss_AddForm\n"));
8455 if (!Printer) {
8456 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8457 OUR_HANDLE(r->in.handle)));
8458 return WERR_BADFID;
8461 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8462 and not a printer admin, then fail */
8464 if ((p->session_info->utok.uid != sec_initial_uid()) &&
8465 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8466 !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8467 p->session_info->info3->base.domain.string,
8468 NULL,
8469 p->session_info->security_token,
8470 lp_printer_admin(snum))) {
8471 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8472 return WERR_ACCESS_DENIED;
8475 switch (form->flags) {
8476 case SPOOLSS_FORM_USER:
8477 case SPOOLSS_FORM_BUILTIN:
8478 case SPOOLSS_FORM_PRINTER:
8479 break;
8480 default:
8481 return WERR_INVALID_PARAM;
8484 status = winreg_printer_binding_handle(p->mem_ctx,
8485 get_session_info_system(),
8486 p->msg_ctx,
8487 &b);
8488 if (!W_ERROR_IS_OK(status)) {
8489 return status;
8492 status = winreg_printer_addform1(p->mem_ctx, b,
8493 form);
8494 if (!W_ERROR_IS_OK(status)) {
8495 return status;
8499 * ChangeID must always be set if this is a printer
8501 if (Printer->printer_type == SPLHND_PRINTER) {
8502 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8503 return WERR_BADFID;
8506 status = winreg_printer_update_changeid(p->mem_ctx, b,
8507 lp_const_servicename(snum));
8508 if (!W_ERROR_IS_OK(status)) {
8509 return status;
8513 return status;
8516 /****************************************************************
8517 _spoolss_DeleteForm
8518 ****************************************************************/
8520 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8521 struct spoolss_DeleteForm *r)
8523 const char *form_name = r->in.form_name;
8524 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8525 int snum = -1;
8526 WERROR status = WERR_OK;
8527 struct dcerpc_binding_handle *b;
8529 DEBUG(5,("_spoolss_DeleteForm\n"));
8531 if (!Printer) {
8532 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8533 OUR_HANDLE(r->in.handle)));
8534 return WERR_BADFID;
8537 if ((p->session_info->utok.uid != sec_initial_uid()) &&
8538 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8539 !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8540 p->session_info->info3->base.domain.string,
8541 NULL,
8542 p->session_info->security_token,
8543 lp_printer_admin(snum))) {
8544 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8545 return WERR_ACCESS_DENIED;
8548 status = winreg_printer_binding_handle(p->mem_ctx,
8549 get_session_info_system(),
8550 p->msg_ctx,
8551 &b);
8552 if (!W_ERROR_IS_OK(status)) {
8553 return status;
8556 status = winreg_printer_deleteform1(p->mem_ctx, b,
8557 form_name);
8558 if (!W_ERROR_IS_OK(status)) {
8559 return status;
8563 * ChangeID must always be set if this is a printer
8565 if (Printer->printer_type == SPLHND_PRINTER) {
8566 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8567 return WERR_BADFID;
8570 status = winreg_printer_update_changeid(p->mem_ctx, b,
8571 lp_const_servicename(snum));
8572 if (!W_ERROR_IS_OK(status)) {
8573 return status;
8577 return status;
8580 /****************************************************************
8581 _spoolss_SetForm
8582 ****************************************************************/
8584 WERROR _spoolss_SetForm(struct pipes_struct *p,
8585 struct spoolss_SetForm *r)
8587 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8588 const char *form_name = r->in.form_name;
8589 int snum = -1;
8590 WERROR status = WERR_OK;
8591 struct dcerpc_binding_handle *b;
8593 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8595 DEBUG(5,("_spoolss_SetForm\n"));
8597 if (!Printer) {
8598 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8599 OUR_HANDLE(r->in.handle)));
8600 return WERR_BADFID;
8603 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8604 and not a printer admin, then fail */
8606 if ((p->session_info->utok.uid != sec_initial_uid()) &&
8607 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8608 !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8609 p->session_info->info3->base.domain.string,
8610 NULL,
8611 p->session_info->security_token,
8612 lp_printer_admin(snum))) {
8613 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8614 return WERR_ACCESS_DENIED;
8617 status = winreg_printer_binding_handle(p->mem_ctx,
8618 get_session_info_system(),
8619 p->msg_ctx,
8620 &b);
8621 if (!W_ERROR_IS_OK(status)) {
8622 return status;
8625 status = winreg_printer_setform1(p->mem_ctx, b,
8626 form_name,
8627 form);
8628 if (!W_ERROR_IS_OK(status)) {
8629 return status;
8633 * ChangeID must always be set if this is a printer
8635 if (Printer->printer_type == SPLHND_PRINTER) {
8636 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8637 return WERR_BADFID;
8640 status = winreg_printer_update_changeid(p->mem_ctx, b,
8641 lp_const_servicename(snum));
8642 if (!W_ERROR_IS_OK(status)) {
8643 return status;
8647 return status;
8650 /****************************************************************************
8651 fill_print_processor1
8652 ****************************************************************************/
8654 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8655 struct spoolss_PrintProcessorInfo1 *r,
8656 const char *print_processor_name)
8658 r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8659 W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8661 return WERR_OK;
8664 /****************************************************************************
8665 enumprintprocessors level 1.
8666 ****************************************************************************/
8668 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8669 union spoolss_PrintProcessorInfo **info_p,
8670 uint32_t *count)
8672 union spoolss_PrintProcessorInfo *info;
8673 WERROR result;
8675 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8676 W_ERROR_HAVE_NO_MEMORY(info);
8678 *count = 1;
8680 result = fill_print_processor1(info, &info[0].info1, "winprint");
8681 if (!W_ERROR_IS_OK(result)) {
8682 goto out;
8685 out:
8686 if (!W_ERROR_IS_OK(result)) {
8687 TALLOC_FREE(info);
8688 *count = 0;
8689 return result;
8692 *info_p = info;
8694 return WERR_OK;
8697 /****************************************************************
8698 _spoolss_EnumPrintProcessors
8699 ****************************************************************/
8701 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
8702 struct spoolss_EnumPrintProcessors *r)
8704 WERROR result;
8706 /* that's an [in out] buffer */
8708 if (!r->in.buffer && (r->in.offered != 0)) {
8709 return WERR_INVALID_PARAM;
8712 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8715 * Enumerate the print processors ...
8717 * Just reply with "winprint", to keep NT happy
8718 * and I can use my nice printer checker.
8721 *r->out.count = 0;
8722 *r->out.needed = 0;
8723 *r->out.info = NULL;
8725 if (!get_short_archi(r->in.environment)) {
8726 return WERR_INVALID_ENVIRONMENT;
8729 switch (r->in.level) {
8730 case 1:
8731 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8732 r->out.count);
8733 break;
8734 default:
8735 return WERR_UNKNOWN_LEVEL;
8738 if (!W_ERROR_IS_OK(result)) {
8739 return result;
8742 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8743 spoolss_EnumPrintProcessors,
8744 *r->out.info, r->in.level,
8745 *r->out.count);
8746 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8747 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8749 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8752 /****************************************************************************
8753 fill_printprocdatatype1
8754 ****************************************************************************/
8756 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8757 struct spoolss_PrintProcDataTypesInfo1 *r,
8758 const char *name_array)
8760 r->name_array = talloc_strdup(mem_ctx, name_array);
8761 W_ERROR_HAVE_NO_MEMORY(r->name_array);
8763 return WERR_OK;
8766 /****************************************************************************
8767 enumprintprocdatatypes level 1.
8768 ****************************************************************************/
8770 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8771 union spoolss_PrintProcDataTypesInfo **info_p,
8772 uint32_t *count)
8774 WERROR result;
8775 union spoolss_PrintProcDataTypesInfo *info;
8777 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8778 W_ERROR_HAVE_NO_MEMORY(info);
8780 *count = 1;
8782 result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8783 if (!W_ERROR_IS_OK(result)) {
8784 goto out;
8787 out:
8788 if (!W_ERROR_IS_OK(result)) {
8789 TALLOC_FREE(info);
8790 *count = 0;
8791 return result;
8794 *info_p = info;
8796 return WERR_OK;
8799 /****************************************************************
8800 _spoolss_EnumPrintProcDataTypes
8801 ****************************************************************/
8803 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
8804 struct spoolss_EnumPrintProcDataTypes *r)
8806 WERROR result;
8808 /* that's an [in out] buffer */
8810 if (!r->in.buffer && (r->in.offered != 0)) {
8811 return WERR_INVALID_PARAM;
8814 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8816 *r->out.count = 0;
8817 *r->out.needed = 0;
8818 *r->out.info = NULL;
8820 if (r->in.print_processor_name == NULL ||
8821 !strequal(r->in.print_processor_name, "winprint")) {
8822 return WERR_UNKNOWN_PRINTPROCESSOR;
8825 switch (r->in.level) {
8826 case 1:
8827 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8828 r->out.count);
8829 break;
8830 default:
8831 return WERR_UNKNOWN_LEVEL;
8834 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8835 spoolss_EnumPrintProcDataTypes,
8836 *r->out.info, r->in.level,
8837 *r->out.count);
8838 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8839 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8841 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8844 /****************************************************************************
8845 fill_monitor_1
8846 ****************************************************************************/
8848 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8849 struct spoolss_MonitorInfo1 *r,
8850 const char *monitor_name)
8852 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8853 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8855 return WERR_OK;
8858 /****************************************************************************
8859 fill_monitor_2
8860 ****************************************************************************/
8862 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8863 struct spoolss_MonitorInfo2 *r,
8864 const char *monitor_name,
8865 const char *environment,
8866 const char *dll_name)
8868 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8869 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8870 r->environment = talloc_strdup(mem_ctx, environment);
8871 W_ERROR_HAVE_NO_MEMORY(r->environment);
8872 r->dll_name = talloc_strdup(mem_ctx, dll_name);
8873 W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8875 return WERR_OK;
8878 /****************************************************************************
8879 enumprintmonitors level 1.
8880 ****************************************************************************/
8882 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8883 union spoolss_MonitorInfo **info_p,
8884 uint32_t *count)
8886 union spoolss_MonitorInfo *info;
8887 WERROR result = WERR_OK;
8889 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8890 W_ERROR_HAVE_NO_MEMORY(info);
8892 *count = 2;
8894 result = fill_monitor_1(info, &info[0].info1,
8895 SPL_LOCAL_PORT);
8896 if (!W_ERROR_IS_OK(result)) {
8897 goto out;
8900 result = fill_monitor_1(info, &info[1].info1,
8901 SPL_TCPIP_PORT);
8902 if (!W_ERROR_IS_OK(result)) {
8903 goto out;
8906 out:
8907 if (!W_ERROR_IS_OK(result)) {
8908 TALLOC_FREE(info);
8909 *count = 0;
8910 return result;
8913 *info_p = info;
8915 return WERR_OK;
8918 /****************************************************************************
8919 enumprintmonitors level 2.
8920 ****************************************************************************/
8922 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8923 union spoolss_MonitorInfo **info_p,
8924 uint32_t *count)
8926 union spoolss_MonitorInfo *info;
8927 WERROR result = WERR_OK;
8929 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8930 W_ERROR_HAVE_NO_MEMORY(info);
8932 *count = 2;
8934 result = fill_monitor_2(info, &info[0].info2,
8935 SPL_LOCAL_PORT,
8936 "Windows NT X86", /* FIXME */
8937 "localmon.dll");
8938 if (!W_ERROR_IS_OK(result)) {
8939 goto out;
8942 result = fill_monitor_2(info, &info[1].info2,
8943 SPL_TCPIP_PORT,
8944 "Windows NT X86", /* FIXME */
8945 "tcpmon.dll");
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 _spoolss_EnumMonitors
8964 ****************************************************************/
8966 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
8967 struct spoolss_EnumMonitors *r)
8969 WERROR result;
8971 /* that's an [in out] buffer */
8973 if (!r->in.buffer && (r->in.offered != 0)) {
8974 return WERR_INVALID_PARAM;
8977 DEBUG(5,("_spoolss_EnumMonitors\n"));
8980 * Enumerate the print monitors ...
8982 * Just reply with "Local Port", to keep NT happy
8983 * and I can use my nice printer checker.
8986 *r->out.count = 0;
8987 *r->out.needed = 0;
8988 *r->out.info = NULL;
8990 switch (r->in.level) {
8991 case 1:
8992 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8993 r->out.count);
8994 break;
8995 case 2:
8996 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8997 r->out.count);
8998 break;
8999 default:
9000 return WERR_UNKNOWN_LEVEL;
9003 if (!W_ERROR_IS_OK(result)) {
9004 return result;
9007 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9008 spoolss_EnumMonitors,
9009 *r->out.info, r->in.level,
9010 *r->out.count);
9011 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9012 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9014 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9017 /****************************************************************************
9018 ****************************************************************************/
9020 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
9021 const print_queue_struct *queue,
9022 int count, int snum,
9023 struct spoolss_PrinterInfo2 *pinfo2,
9024 uint32_t jobid,
9025 struct spoolss_JobInfo1 *r)
9027 int i = 0;
9028 bool found = false;
9030 for (i=0; i<count; i++) {
9031 if (queue[i].job == (int)jobid) {
9032 found = true;
9033 break;
9037 if (found == false) {
9038 /* NT treats not found as bad param... yet another bad choice */
9039 return WERR_INVALID_PARAM;
9042 return fill_job_info1(mem_ctx,
9044 &queue[i],
9046 snum,
9047 pinfo2);
9050 /****************************************************************************
9051 ****************************************************************************/
9053 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9054 const print_queue_struct *queue,
9055 int count, int snum,
9056 struct spoolss_PrinterInfo2 *pinfo2,
9057 uint32_t jobid,
9058 struct spoolss_JobInfo2 *r)
9060 int i = 0;
9061 bool found = false;
9062 struct spoolss_DeviceMode *devmode;
9063 WERROR result;
9065 for (i=0; i<count; i++) {
9066 if (queue[i].job == (int)jobid) {
9067 found = true;
9068 break;
9072 if (found == false) {
9073 /* NT treats not found as bad param... yet another bad
9074 choice */
9075 return WERR_INVALID_PARAM;
9079 * if the print job does not have a DEVMODE associated with it,
9080 * just use the one for the printer. A NULL devicemode is not
9081 * a failure condition
9084 devmode = print_job_devmode(lp_const_servicename(snum), jobid);
9085 if (!devmode) {
9086 result = spoolss_create_default_devmode(mem_ctx,
9087 pinfo2->printername,
9088 &devmode);
9089 if (!W_ERROR_IS_OK(result)) {
9090 DEBUG(3, ("Can't proceed w/o a devmode!"));
9091 return result;
9095 return fill_job_info2(mem_ctx,
9097 &queue[i],
9099 snum,
9100 pinfo2,
9101 devmode);
9104 /****************************************************************
9105 _spoolss_GetJob
9106 ****************************************************************/
9108 WERROR _spoolss_GetJob(struct pipes_struct *p,
9109 struct spoolss_GetJob *r)
9111 WERROR result = WERR_OK;
9112 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9113 int snum;
9114 int count;
9115 print_queue_struct *queue = NULL;
9116 print_status_struct prt_status;
9118 /* that's an [in out] buffer */
9120 if (!r->in.buffer && (r->in.offered != 0)) {
9121 return WERR_INVALID_PARAM;
9124 DEBUG(5,("_spoolss_GetJob\n"));
9126 *r->out.needed = 0;
9128 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9129 return WERR_BADFID;
9132 result = winreg_get_printer_internal(p->mem_ctx,
9133 get_session_info_system(),
9134 p->msg_ctx,
9135 lp_const_servicename(snum),
9136 &pinfo2);
9137 if (!W_ERROR_IS_OK(result)) {
9138 return result;
9141 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9143 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9144 count, prt_status.status, prt_status.message));
9146 switch (r->in.level) {
9147 case 1:
9148 result = getjob_level_1(p->mem_ctx,
9149 queue, count, snum, pinfo2,
9150 r->in.job_id, &r->out.info->info1);
9151 break;
9152 case 2:
9153 result = getjob_level_2(p->mem_ctx,
9154 queue, count, snum, pinfo2,
9155 r->in.job_id, &r->out.info->info2);
9156 break;
9157 default:
9158 result = WERR_UNKNOWN_LEVEL;
9159 break;
9162 SAFE_FREE(queue);
9163 TALLOC_FREE(pinfo2);
9165 if (!W_ERROR_IS_OK(result)) {
9166 TALLOC_FREE(r->out.info);
9167 return result;
9170 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9171 r->in.level);
9172 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9174 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9177 /****************************************************************
9178 _spoolss_GetPrinterDataEx
9179 ****************************************************************/
9181 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9182 struct spoolss_GetPrinterDataEx *r)
9185 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9186 const char *printer;
9187 int snum = 0;
9188 WERROR result = WERR_OK;
9189 DATA_BLOB blob;
9190 enum winreg_Type val_type = REG_NONE;
9191 uint8_t *val_data = NULL;
9192 uint32_t val_size = 0;
9193 struct dcerpc_binding_handle *b;
9195 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9197 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9198 r->in.key_name, r->in.value_name));
9200 /* in case of problem, return some default values */
9202 *r->out.needed = 0;
9203 *r->out.type = REG_NONE;
9205 if (!Printer) {
9206 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9207 OUR_HANDLE(r->in.handle)));
9208 result = WERR_BADFID;
9209 goto done;
9212 /* Is the handle to a printer or to the server? */
9214 if (Printer->printer_type == SPLHND_SERVER) {
9216 union spoolss_PrinterData data;
9218 result = getprinterdata_printer_server(p->mem_ctx,
9219 r->in.value_name,
9220 r->out.type,
9221 &data);
9222 if (!W_ERROR_IS_OK(result)) {
9223 return result;
9226 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
9227 *r->out.type, &data);
9228 if (!W_ERROR_IS_OK(result)) {
9229 return result;
9232 *r->out.needed = blob.length;
9234 if (r->in.offered >= *r->out.needed) {
9235 memcpy(r->out.data, blob.data, blob.length);
9238 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9241 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9242 return WERR_BADFID;
9244 printer = lp_const_servicename(snum);
9246 /* check to see if the keyname is valid */
9247 if (!strlen(r->in.key_name)) {
9248 return WERR_INVALID_PARAM;
9251 result = winreg_printer_binding_handle(p->mem_ctx,
9252 get_session_info_system(),
9253 p->msg_ctx,
9254 &b);
9255 if (!W_ERROR_IS_OK(result)) {
9256 return result;
9259 /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9260 if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9261 strequal(r->in.value_name, "ChangeId")) {
9262 *r->out.type = REG_DWORD;
9263 *r->out.needed = 4;
9264 if (r->in.offered >= *r->out.needed) {
9265 uint32_t changeid = 0;
9267 result = winreg_printer_get_changeid(p->mem_ctx, b,
9268 printer,
9269 &changeid);
9270 if (!W_ERROR_IS_OK(result)) {
9271 return result;
9274 SIVAL(r->out.data, 0, changeid);
9275 result = WERR_OK;
9277 goto done;
9280 result = winreg_get_printer_dataex(p->mem_ctx, b,
9281 printer,
9282 r->in.key_name,
9283 r->in.value_name,
9284 &val_type,
9285 &val_data,
9286 &val_size);
9287 if (!W_ERROR_IS_OK(result)) {
9288 return result;
9291 *r->out.needed = val_size;
9292 *r->out.type = val_type;
9294 if (r->in.offered >= *r->out.needed) {
9295 memcpy(r->out.data, val_data, val_size);
9298 done:
9299 /* retain type when returning WERR_MORE_DATA */
9300 r->out.data = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
9302 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9305 /****************************************************************
9306 _spoolss_SetPrinterDataEx
9307 ****************************************************************/
9309 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9310 struct spoolss_SetPrinterDataEx *r)
9312 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9313 int snum = 0;
9314 WERROR result = WERR_OK;
9315 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9316 char *oid_string;
9317 struct dcerpc_binding_handle *b;
9319 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9321 /* From MSDN documentation of SetPrinterDataEx: pass request to
9322 SetPrinterData if key is "PrinterDriverData" */
9324 if (!Printer) {
9325 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9326 OUR_HANDLE(r->in.handle)));
9327 return WERR_BADFID;
9330 if (Printer->printer_type == SPLHND_SERVER) {
9331 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9332 "Not implemented for server handles yet\n"));
9333 return WERR_INVALID_PARAM;
9336 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9337 return WERR_BADFID;
9341 * Access check : NT returns "access denied" if you make a
9342 * SetPrinterData call without the necessary privildge.
9343 * we were originally returning OK if nothing changed
9344 * which made Win2k issue **a lot** of SetPrinterData
9345 * when connecting to a printer --jerry
9348 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9349 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9350 "change denied by handle access permissions\n"));
9351 return WERR_ACCESS_DENIED;
9354 result = winreg_printer_binding_handle(p->mem_ctx,
9355 get_session_info_system(),
9356 p->msg_ctx,
9357 &b);
9358 if (!W_ERROR_IS_OK(result)) {
9359 return result;
9362 result = winreg_get_printer(Printer, b,
9363 lp_servicename(snum),
9364 &pinfo2);
9365 if (!W_ERROR_IS_OK(result)) {
9366 return result;
9369 /* check for OID in valuename */
9371 oid_string = strchr(r->in.value_name, ',');
9372 if (oid_string) {
9373 *oid_string = '\0';
9374 oid_string++;
9377 /* save the registry data */
9379 result = winreg_set_printer_dataex(p->mem_ctx, b,
9380 pinfo2->sharename,
9381 r->in.key_name,
9382 r->in.value_name,
9383 r->in.type,
9384 r->in.data,
9385 r->in.offered);
9387 if (W_ERROR_IS_OK(result)) {
9388 /* save the OID if one was specified */
9389 if (oid_string) {
9390 char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9391 r->in.key_name, SPOOL_OID_KEY);
9392 if (!str) {
9393 result = WERR_NOMEM;
9394 goto done;
9398 * I'm not checking the status here on purpose. Don't know
9399 * if this is right, but I'm returning the status from the
9400 * previous set_printer_dataex() call. I have no idea if
9401 * this is right. --jerry
9403 winreg_set_printer_dataex(p->mem_ctx, b,
9404 pinfo2->sharename,
9405 str,
9406 r->in.value_name,
9407 REG_SZ,
9408 (uint8_t *) oid_string,
9409 strlen(oid_string) + 1);
9412 result = winreg_printer_update_changeid(p->mem_ctx, b,
9413 lp_const_servicename(snum));
9417 done:
9418 talloc_free(pinfo2);
9419 return result;
9422 /****************************************************************
9423 _spoolss_DeletePrinterDataEx
9424 ****************************************************************/
9426 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9427 struct spoolss_DeletePrinterDataEx *r)
9429 const char *printer;
9430 int snum=0;
9431 WERROR status = WERR_OK;
9432 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9434 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9436 if (!Printer) {
9437 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9438 "Invalid handle (%s:%u:%u).\n",
9439 OUR_HANDLE(r->in.handle)));
9440 return WERR_BADFID;
9443 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9444 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9445 "printer properties change denied by handle\n"));
9446 return WERR_ACCESS_DENIED;
9449 if (!r->in.value_name || !r->in.key_name) {
9450 return WERR_NOMEM;
9453 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9454 return WERR_BADFID;
9456 printer = lp_const_servicename(snum);
9458 status = winreg_delete_printer_dataex_internal(p->mem_ctx,
9459 get_session_info_system(),
9460 p->msg_ctx,
9461 printer,
9462 r->in.key_name,
9463 r->in.value_name);
9464 if (W_ERROR_IS_OK(status)) {
9465 status = winreg_printer_update_changeid_internal(p->mem_ctx,
9466 get_session_info_system(),
9467 p->msg_ctx,
9468 printer);
9471 return status;
9474 /****************************************************************
9475 _spoolss_EnumPrinterKey
9476 ****************************************************************/
9478 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9479 struct spoolss_EnumPrinterKey *r)
9481 uint32_t num_keys;
9482 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9483 int snum = 0;
9484 WERROR result = WERR_BADFILE;
9485 const char **array = NULL;
9486 DATA_BLOB blob;
9488 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9490 if (!Printer) {
9491 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9492 OUR_HANDLE(r->in.handle)));
9493 return WERR_BADFID;
9496 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9497 return WERR_BADFID;
9500 result = winreg_enum_printer_key_internal(p->mem_ctx,
9501 get_session_info_system(),
9502 p->msg_ctx,
9503 lp_const_servicename(snum),
9504 r->in.key_name,
9505 &num_keys,
9506 &array);
9507 if (!W_ERROR_IS_OK(result)) {
9508 goto done;
9511 if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9512 result = WERR_NOMEM;
9513 goto done;
9516 *r->out._ndr_size = r->in.offered / 2;
9517 *r->out.needed = blob.length;
9519 if (r->in.offered < *r->out.needed) {
9520 result = WERR_MORE_DATA;
9521 } else {
9522 result = WERR_OK;
9523 r->out.key_buffer->string_array = array;
9526 done:
9527 if (!W_ERROR_IS_OK(result)) {
9528 TALLOC_FREE(array);
9529 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9530 *r->out.needed = 0;
9534 return result;
9537 /****************************************************************
9538 _spoolss_DeletePrinterKey
9539 ****************************************************************/
9541 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9542 struct spoolss_DeletePrinterKey *r)
9544 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9545 int snum=0;
9546 WERROR status;
9547 const char *printer;
9548 struct dcerpc_binding_handle *b;
9550 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9552 if (!Printer) {
9553 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9554 OUR_HANDLE(r->in.handle)));
9555 return WERR_BADFID;
9558 /* if keyname == NULL, return error */
9559 if ( !r->in.key_name )
9560 return WERR_INVALID_PARAM;
9562 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9563 return WERR_BADFID;
9566 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9567 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9568 "printer properties change denied by handle\n"));
9569 return WERR_ACCESS_DENIED;
9572 printer = lp_const_servicename(snum);
9574 status = winreg_printer_binding_handle(p->mem_ctx,
9575 get_session_info_system(),
9576 p->msg_ctx,
9577 &b);
9578 if (!W_ERROR_IS_OK(status)) {
9579 return status;
9582 /* delete the key and all subkeys */
9583 status = winreg_delete_printer_key(p->mem_ctx, b,
9584 printer,
9585 r->in.key_name);
9586 if (W_ERROR_IS_OK(status)) {
9587 status = winreg_printer_update_changeid(p->mem_ctx, b,
9588 printer);
9591 return status;
9594 /****************************************************************
9595 _spoolss_EnumPrinterDataEx
9596 ****************************************************************/
9598 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
9599 struct spoolss_EnumPrinterDataEx *r)
9601 uint32_t count = 0;
9602 struct spoolss_PrinterEnumValues *info = NULL;
9603 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9604 int snum;
9605 WERROR result;
9607 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9609 *r->out.count = 0;
9610 *r->out.needed = 0;
9611 *r->out.info = NULL;
9613 if (!Printer) {
9614 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9615 OUR_HANDLE(r->in.handle)));
9616 return WERR_BADFID;
9620 * first check for a keyname of NULL or "". Win2k seems to send
9621 * this a lot and we should send back WERR_INVALID_PARAM
9622 * no need to spend time looking up the printer in this case.
9623 * --jerry
9626 if (!strlen(r->in.key_name)) {
9627 result = WERR_INVALID_PARAM;
9628 goto done;
9631 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9632 return WERR_BADFID;
9635 /* now look for a match on the key name */
9636 result = winreg_enum_printer_dataex_internal(p->mem_ctx,
9637 get_session_info_system(),
9638 p->msg_ctx,
9639 lp_const_servicename(snum),
9640 r->in.key_name,
9641 &count,
9642 &info);
9643 if (!W_ERROR_IS_OK(result)) {
9644 goto done;
9647 #if 0 /* FIXME - gd */
9648 /* housekeeping information in the reply */
9650 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9651 * the hand marshalled container size is a multiple
9652 * of 4 bytes for RPC alignment.
9655 if (needed % 4) {
9656 needed += 4-(needed % 4);
9658 #endif
9659 *r->out.count = count;
9660 *r->out.info = info;
9662 done:
9663 if (!W_ERROR_IS_OK(result)) {
9664 return result;
9667 *r->out.needed = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9668 spoolss_EnumPrinterDataEx,
9669 *r->out.info,
9670 *r->out.count);
9671 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9672 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9674 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9677 /****************************************************************************
9678 ****************************************************************************/
9680 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9681 const char *servername,
9682 const char *environment,
9683 struct spoolss_PrintProcessorDirectoryInfo1 *r)
9685 WERROR werr;
9686 char *path = NULL;
9688 werr = compose_spoolss_server_path(mem_ctx,
9689 servername,
9690 environment,
9691 SPOOLSS_PRTPROCS_PATH,
9692 &path);
9693 if (!W_ERROR_IS_OK(werr)) {
9694 return werr;
9697 DEBUG(4,("print processor directory: [%s]\n", path));
9699 r->directory_name = path;
9701 return WERR_OK;
9704 /****************************************************************
9705 _spoolss_GetPrintProcessorDirectory
9706 ****************************************************************/
9708 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
9709 struct spoolss_GetPrintProcessorDirectory *r)
9711 WERROR result;
9712 char *prnproc_share = NULL;
9713 bool prnproc_share_exists = false;
9714 int snum;
9716 /* that's an [in out] buffer */
9718 if (!r->in.buffer && (r->in.offered != 0)) {
9719 return WERR_INVALID_PARAM;
9722 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9723 r->in.level));
9725 *r->out.needed = 0;
9727 /* r->in.level is ignored */
9729 /* We always should reply with a local print processor directory so that
9730 * users are not forced to have a [prnproc$] share on the Samba spoolss
9731 * server, if users decide to do so, lets announce it though - Guenther */
9733 snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
9734 if (!prnproc_share) {
9735 return WERR_NOMEM;
9737 if (snum != -1) {
9738 prnproc_share_exists = true;
9741 result = getprintprocessordirectory_level_1(p->mem_ctx,
9742 prnproc_share_exists ? r->in.server : NULL,
9743 r->in.environment,
9744 &r->out.info->info1);
9745 if (!W_ERROR_IS_OK(result)) {
9746 TALLOC_FREE(r->out.info);
9747 return result;
9750 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
9751 r->out.info, r->in.level);
9752 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9754 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9757 /*******************************************************************
9758 ********************************************************************/
9760 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9761 const char *dllname)
9763 enum ndr_err_code ndr_err;
9764 struct spoolss_MonitorUi ui;
9766 ui.dll_name = dllname;
9768 ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
9769 (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9770 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9771 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9773 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9776 /*******************************************************************
9777 Streams the monitor UI DLL name in UNICODE
9778 *******************************************************************/
9780 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9781 struct security_token *token, DATA_BLOB *in,
9782 DATA_BLOB *out, uint32_t *needed)
9784 const char *dllname = "tcpmonui.dll";
9786 *needed = (strlen(dllname)+1) * 2;
9788 if (out->length < *needed) {
9789 return WERR_INSUFFICIENT_BUFFER;
9792 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9793 return WERR_NOMEM;
9796 return WERR_OK;
9799 /*******************************************************************
9800 ********************************************************************/
9802 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9803 struct spoolss_PortData1 *port1,
9804 const DATA_BLOB *buf)
9806 enum ndr_err_code ndr_err;
9807 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
9808 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9809 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9810 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9812 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9815 /*******************************************************************
9816 ********************************************************************/
9818 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9819 struct spoolss_PortData2 *port2,
9820 const DATA_BLOB *buf)
9822 enum ndr_err_code ndr_err;
9823 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
9824 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9825 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9826 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9828 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9831 /*******************************************************************
9832 Create a new TCP/IP port
9833 *******************************************************************/
9835 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9836 struct security_token *token, DATA_BLOB *in,
9837 DATA_BLOB *out, uint32_t *needed)
9839 struct spoolss_PortData1 port1;
9840 struct spoolss_PortData2 port2;
9841 char *device_uri = NULL;
9842 uint32_t version;
9844 const char *portname;
9845 const char *hostaddress;
9846 const char *queue;
9847 uint32_t port_number;
9848 uint32_t protocol;
9850 /* peek for spoolss_PortData version */
9852 if (!in || (in->length < (128 + 4))) {
9853 return WERR_GENERAL_FAILURE;
9856 version = IVAL(in->data, 128);
9858 switch (version) {
9859 case 1:
9860 ZERO_STRUCT(port1);
9862 if (!pull_port_data_1(mem_ctx, &port1, in)) {
9863 return WERR_NOMEM;
9866 portname = port1.portname;
9867 hostaddress = port1.hostaddress;
9868 queue = port1.queue;
9869 protocol = port1.protocol;
9870 port_number = port1.port_number;
9872 break;
9873 case 2:
9874 ZERO_STRUCT(port2);
9876 if (!pull_port_data_2(mem_ctx, &port2, in)) {
9877 return WERR_NOMEM;
9880 portname = port2.portname;
9881 hostaddress = port2.hostaddress;
9882 queue = port2.queue;
9883 protocol = port2.protocol;
9884 port_number = port2.port_number;
9886 break;
9887 default:
9888 DEBUG(1,("xcvtcp_addport: "
9889 "unknown version of port_data: %d\n", version));
9890 return WERR_UNKNOWN_PORT;
9893 /* create the device URI and call the add_port_hook() */
9895 switch (protocol) {
9896 case PROTOCOL_RAWTCP_TYPE:
9897 device_uri = talloc_asprintf(mem_ctx,
9898 "socket://%s:%d/", hostaddress,
9899 port_number);
9900 break;
9902 case PROTOCOL_LPR_TYPE:
9903 device_uri = talloc_asprintf(mem_ctx,
9904 "lpr://%s/%s", hostaddress, queue );
9905 break;
9907 default:
9908 return WERR_UNKNOWN_PORT;
9911 if (!device_uri) {
9912 return WERR_NOMEM;
9915 return add_port_hook(mem_ctx, token, portname, device_uri);
9918 /*******************************************************************
9919 *******************************************************************/
9921 struct xcv_api_table xcvtcp_cmds[] = {
9922 { "MonitorUI", xcvtcp_monitorui },
9923 { "AddPort", xcvtcp_addport},
9924 { NULL, NULL }
9927 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9928 struct security_token *token, const char *command,
9929 DATA_BLOB *inbuf,
9930 DATA_BLOB *outbuf,
9931 uint32_t *needed )
9933 int i;
9935 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9937 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9938 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9939 return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9942 return WERR_BADFUNC;
9945 /*******************************************************************
9946 *******************************************************************/
9947 #if 0 /* don't support management using the "Local Port" monitor */
9949 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9950 struct security_token *token, DATA_BLOB *in,
9951 DATA_BLOB *out, uint32_t *needed)
9953 const char *dllname = "localui.dll";
9955 *needed = (strlen(dllname)+1) * 2;
9957 if (out->length < *needed) {
9958 return WERR_INSUFFICIENT_BUFFER;
9961 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9962 return WERR_NOMEM;
9965 return WERR_OK;
9968 /*******************************************************************
9969 *******************************************************************/
9971 struct xcv_api_table xcvlocal_cmds[] = {
9972 { "MonitorUI", xcvlocal_monitorui },
9973 { NULL, NULL }
9975 #else
9976 struct xcv_api_table xcvlocal_cmds[] = {
9977 { NULL, NULL }
9979 #endif
9983 /*******************************************************************
9984 *******************************************************************/
9986 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9987 struct security_token *token, const char *command,
9988 DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9989 uint32_t *needed)
9991 int i;
9993 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9995 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9996 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9997 return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9999 return WERR_BADFUNC;
10002 /****************************************************************
10003 _spoolss_XcvData
10004 ****************************************************************/
10006 WERROR _spoolss_XcvData(struct pipes_struct *p,
10007 struct spoolss_XcvData *r)
10009 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10010 DATA_BLOB out_data = data_blob_null;
10011 WERROR werror;
10013 if (!Printer) {
10014 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10015 OUR_HANDLE(r->in.handle)));
10016 return WERR_BADFID;
10019 /* Has to be a handle to the TCP/IP port monitor */
10021 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10022 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10023 return WERR_BADFID;
10026 /* requires administrative access to the server */
10028 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10029 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10030 return WERR_ACCESS_DENIED;
10033 /* Allocate the outgoing buffer */
10035 if (r->in.out_data_size) {
10036 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10037 if (out_data.data == NULL) {
10038 return WERR_NOMEM;
10042 switch ( Printer->printer_type ) {
10043 case SPLHND_PORTMON_TCP:
10044 werror = process_xcvtcp_command(p->mem_ctx,
10045 p->session_info->security_token,
10046 r->in.function_name,
10047 &r->in.in_data, &out_data,
10048 r->out.needed);
10049 break;
10050 case SPLHND_PORTMON_LOCAL:
10051 werror = process_xcvlocal_command(p->mem_ctx,
10052 p->session_info->security_token,
10053 r->in.function_name,
10054 &r->in.in_data, &out_data,
10055 r->out.needed);
10056 break;
10057 default:
10058 werror = WERR_INVALID_PRINT_MONITOR;
10061 if (!W_ERROR_IS_OK(werror)) {
10062 return werror;
10065 *r->out.status_code = 0;
10067 if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10068 memcpy(r->out.out_data, out_data.data,
10069 MIN(r->in.out_data_size, out_data.length));
10072 return WERR_OK;
10075 /****************************************************************
10076 _spoolss_AddPrintProcessor
10077 ****************************************************************/
10079 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10080 struct spoolss_AddPrintProcessor *r)
10082 /* for now, just indicate success and ignore the add. We'll
10083 automatically set the winprint processor for printer
10084 entries later. Used to debug the LexMark Optra S 1855 PCL
10085 driver --jerry */
10087 return WERR_OK;
10090 /****************************************************************
10091 _spoolss_AddPort
10092 ****************************************************************/
10094 WERROR _spoolss_AddPort(struct pipes_struct *p,
10095 struct spoolss_AddPort *r)
10097 /* do what w2k3 does */
10099 return WERR_NOT_SUPPORTED;
10102 /****************************************************************
10103 _spoolss_GetPrinterDriver
10104 ****************************************************************/
10106 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10107 struct spoolss_GetPrinterDriver *r)
10109 p->rng_fault_state = true;
10110 return WERR_NOT_SUPPORTED;
10113 /****************************************************************
10114 _spoolss_ReadPrinter
10115 ****************************************************************/
10117 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10118 struct spoolss_ReadPrinter *r)
10120 p->rng_fault_state = true;
10121 return WERR_NOT_SUPPORTED;
10124 /****************************************************************
10125 _spoolss_WaitForPrinterChange
10126 ****************************************************************/
10128 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10129 struct spoolss_WaitForPrinterChange *r)
10131 p->rng_fault_state = true;
10132 return WERR_NOT_SUPPORTED;
10135 /****************************************************************
10136 _spoolss_ConfigurePort
10137 ****************************************************************/
10139 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10140 struct spoolss_ConfigurePort *r)
10142 p->rng_fault_state = true;
10143 return WERR_NOT_SUPPORTED;
10146 /****************************************************************
10147 _spoolss_DeletePort
10148 ****************************************************************/
10150 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10151 struct spoolss_DeletePort *r)
10153 p->rng_fault_state = true;
10154 return WERR_NOT_SUPPORTED;
10157 /****************************************************************
10158 _spoolss_CreatePrinterIC
10159 ****************************************************************/
10161 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10162 struct spoolss_CreatePrinterIC *r)
10164 p->rng_fault_state = true;
10165 return WERR_NOT_SUPPORTED;
10168 /****************************************************************
10169 _spoolss_PlayGDIScriptOnPrinterIC
10170 ****************************************************************/
10172 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10173 struct spoolss_PlayGDIScriptOnPrinterIC *r)
10175 p->rng_fault_state = true;
10176 return WERR_NOT_SUPPORTED;
10179 /****************************************************************
10180 _spoolss_DeletePrinterIC
10181 ****************************************************************/
10183 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10184 struct spoolss_DeletePrinterIC *r)
10186 p->rng_fault_state = true;
10187 return WERR_NOT_SUPPORTED;
10190 /****************************************************************
10191 _spoolss_AddPrinterConnection
10192 ****************************************************************/
10194 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10195 struct spoolss_AddPrinterConnection *r)
10197 p->rng_fault_state = true;
10198 return WERR_NOT_SUPPORTED;
10201 /****************************************************************
10202 _spoolss_DeletePrinterConnection
10203 ****************************************************************/
10205 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10206 struct spoolss_DeletePrinterConnection *r)
10208 p->rng_fault_state = true;
10209 return WERR_NOT_SUPPORTED;
10212 /****************************************************************
10213 _spoolss_PrinterMessageBox
10214 ****************************************************************/
10216 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10217 struct spoolss_PrinterMessageBox *r)
10219 p->rng_fault_state = true;
10220 return WERR_NOT_SUPPORTED;
10223 /****************************************************************
10224 _spoolss_AddMonitor
10225 ****************************************************************/
10227 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10228 struct spoolss_AddMonitor *r)
10230 p->rng_fault_state = true;
10231 return WERR_NOT_SUPPORTED;
10234 /****************************************************************
10235 _spoolss_DeleteMonitor
10236 ****************************************************************/
10238 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10239 struct spoolss_DeleteMonitor *r)
10241 p->rng_fault_state = true;
10242 return WERR_NOT_SUPPORTED;
10245 /****************************************************************
10246 _spoolss_DeletePrintProcessor
10247 ****************************************************************/
10249 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10250 struct spoolss_DeletePrintProcessor *r)
10252 p->rng_fault_state = true;
10253 return WERR_NOT_SUPPORTED;
10256 /****************************************************************
10257 _spoolss_AddPrintProvidor
10258 ****************************************************************/
10260 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10261 struct spoolss_AddPrintProvidor *r)
10263 p->rng_fault_state = true;
10264 return WERR_NOT_SUPPORTED;
10267 /****************************************************************
10268 _spoolss_DeletePrintProvidor
10269 ****************************************************************/
10271 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10272 struct spoolss_DeletePrintProvidor *r)
10274 p->rng_fault_state = true;
10275 return WERR_NOT_SUPPORTED;
10278 /****************************************************************
10279 _spoolss_FindFirstPrinterChangeNotification
10280 ****************************************************************/
10282 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10283 struct spoolss_FindFirstPrinterChangeNotification *r)
10285 p->rng_fault_state = true;
10286 return WERR_NOT_SUPPORTED;
10289 /****************************************************************
10290 _spoolss_FindNextPrinterChangeNotification
10291 ****************************************************************/
10293 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10294 struct spoolss_FindNextPrinterChangeNotification *r)
10296 p->rng_fault_state = true;
10297 return WERR_NOT_SUPPORTED;
10300 /****************************************************************
10301 _spoolss_RouterFindFirstPrinterChangeNotificationOld
10302 ****************************************************************/
10304 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10305 struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10307 p->rng_fault_state = true;
10308 return WERR_NOT_SUPPORTED;
10311 /****************************************************************
10312 _spoolss_ReplyOpenPrinter
10313 ****************************************************************/
10315 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10316 struct spoolss_ReplyOpenPrinter *r)
10318 p->rng_fault_state = true;
10319 return WERR_NOT_SUPPORTED;
10322 /****************************************************************
10323 _spoolss_RouterReplyPrinter
10324 ****************************************************************/
10326 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10327 struct spoolss_RouterReplyPrinter *r)
10329 p->rng_fault_state = true;
10330 return WERR_NOT_SUPPORTED;
10333 /****************************************************************
10334 _spoolss_ReplyClosePrinter
10335 ****************************************************************/
10337 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10338 struct spoolss_ReplyClosePrinter *r)
10340 p->rng_fault_state = true;
10341 return WERR_NOT_SUPPORTED;
10344 /****************************************************************
10345 _spoolss_AddPortEx
10346 ****************************************************************/
10348 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10349 struct spoolss_AddPortEx *r)
10351 p->rng_fault_state = true;
10352 return WERR_NOT_SUPPORTED;
10355 /****************************************************************
10356 _spoolss_RouterFindFirstPrinterChangeNotification
10357 ****************************************************************/
10359 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10360 struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10362 p->rng_fault_state = true;
10363 return WERR_NOT_SUPPORTED;
10366 /****************************************************************
10367 _spoolss_SpoolerInit
10368 ****************************************************************/
10370 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10371 struct spoolss_SpoolerInit *r)
10373 p->rng_fault_state = true;
10374 return WERR_NOT_SUPPORTED;
10377 /****************************************************************
10378 _spoolss_ResetPrinterEx
10379 ****************************************************************/
10381 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10382 struct spoolss_ResetPrinterEx *r)
10384 p->rng_fault_state = true;
10385 return WERR_NOT_SUPPORTED;
10388 /****************************************************************
10389 _spoolss_RouterReplyPrinterEx
10390 ****************************************************************/
10392 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10393 struct spoolss_RouterReplyPrinterEx *r)
10395 p->rng_fault_state = true;
10396 return WERR_NOT_SUPPORTED;
10399 /****************************************************************
10400 _spoolss_44
10401 ****************************************************************/
10403 WERROR _spoolss_44(struct pipes_struct *p,
10404 struct spoolss_44 *r)
10406 p->rng_fault_state = true;
10407 return WERR_NOT_SUPPORTED;
10410 /****************************************************************
10411 _spoolss_SetPort
10412 ****************************************************************/
10414 WERROR _spoolss_SetPort(struct pipes_struct *p,
10415 struct spoolss_SetPort *r)
10417 p->rng_fault_state = true;
10418 return WERR_NOT_SUPPORTED;
10421 /****************************************************************
10422 _spoolss_4a
10423 ****************************************************************/
10425 WERROR _spoolss_4a(struct pipes_struct *p,
10426 struct spoolss_4a *r)
10428 p->rng_fault_state = true;
10429 return WERR_NOT_SUPPORTED;
10432 /****************************************************************
10433 _spoolss_4b
10434 ****************************************************************/
10436 WERROR _spoolss_4b(struct pipes_struct *p,
10437 struct spoolss_4b *r)
10439 p->rng_fault_state = true;
10440 return WERR_NOT_SUPPORTED;
10443 /****************************************************************
10444 _spoolss_4c
10445 ****************************************************************/
10447 WERROR _spoolss_4c(struct pipes_struct *p,
10448 struct spoolss_4c *r)
10450 p->rng_fault_state = true;
10451 return WERR_NOT_SUPPORTED;
10454 /****************************************************************
10455 _spoolss_53
10456 ****************************************************************/
10458 WERROR _spoolss_53(struct pipes_struct *p,
10459 struct spoolss_53 *r)
10461 p->rng_fault_state = true;
10462 return WERR_NOT_SUPPORTED;
10465 /****************************************************************
10466 _spoolss_AddPerMachineConnection
10467 ****************************************************************/
10469 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
10470 struct spoolss_AddPerMachineConnection *r)
10472 p->rng_fault_state = true;
10473 return WERR_NOT_SUPPORTED;
10476 /****************************************************************
10477 _spoolss_DeletePerMachineConnection
10478 ****************************************************************/
10480 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
10481 struct spoolss_DeletePerMachineConnection *r)
10483 p->rng_fault_state = true;
10484 return WERR_NOT_SUPPORTED;
10487 /****************************************************************
10488 _spoolss_EnumPerMachineConnections
10489 ****************************************************************/
10491 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
10492 struct spoolss_EnumPerMachineConnections *r)
10494 p->rng_fault_state = true;
10495 return WERR_NOT_SUPPORTED;
10498 /****************************************************************
10499 _spoolss_5a
10500 ****************************************************************/
10502 WERROR _spoolss_5a(struct pipes_struct *p,
10503 struct spoolss_5a *r)
10505 p->rng_fault_state = true;
10506 return WERR_NOT_SUPPORTED;
10509 /****************************************************************
10510 _spoolss_5b
10511 ****************************************************************/
10513 WERROR _spoolss_5b(struct pipes_struct *p,
10514 struct spoolss_5b *r)
10516 p->rng_fault_state = true;
10517 return WERR_NOT_SUPPORTED;
10520 /****************************************************************
10521 _spoolss_5c
10522 ****************************************************************/
10524 WERROR _spoolss_5c(struct pipes_struct *p,
10525 struct spoolss_5c *r)
10527 p->rng_fault_state = true;
10528 return WERR_NOT_SUPPORTED;
10531 /****************************************************************
10532 _spoolss_5d
10533 ****************************************************************/
10535 WERROR _spoolss_5d(struct pipes_struct *p,
10536 struct spoolss_5d *r)
10538 p->rng_fault_state = true;
10539 return WERR_NOT_SUPPORTED;
10542 /****************************************************************
10543 _spoolss_5e
10544 ****************************************************************/
10546 WERROR _spoolss_5e(struct pipes_struct *p,
10547 struct spoolss_5e *r)
10549 p->rng_fault_state = true;
10550 return WERR_NOT_SUPPORTED;
10553 /****************************************************************
10554 _spoolss_5f
10555 ****************************************************************/
10557 WERROR _spoolss_5f(struct pipes_struct *p,
10558 struct spoolss_5f *r)
10560 p->rng_fault_state = true;
10561 return WERR_NOT_SUPPORTED;
10564 /****************************************************************
10565 _spoolss_60
10566 ****************************************************************/
10568 WERROR _spoolss_60(struct pipes_struct *p,
10569 struct spoolss_60 *r)
10571 p->rng_fault_state = true;
10572 return WERR_NOT_SUPPORTED;
10575 /****************************************************************
10576 _spoolss_61
10577 ****************************************************************/
10579 WERROR _spoolss_61(struct pipes_struct *p,
10580 struct spoolss_61 *r)
10582 p->rng_fault_state = true;
10583 return WERR_NOT_SUPPORTED;
10586 /****************************************************************
10587 _spoolss_62
10588 ****************************************************************/
10590 WERROR _spoolss_62(struct pipes_struct *p,
10591 struct spoolss_62 *r)
10593 p->rng_fault_state = true;
10594 return WERR_NOT_SUPPORTED;
10597 /****************************************************************
10598 _spoolss_63
10599 ****************************************************************/
10601 WERROR _spoolss_63(struct pipes_struct *p,
10602 struct spoolss_63 *r)
10604 p->rng_fault_state = true;
10605 return WERR_NOT_SUPPORTED;
10608 /****************************************************************
10609 _spoolss_64
10610 ****************************************************************/
10612 WERROR _spoolss_64(struct pipes_struct *p,
10613 struct spoolss_64 *r)
10615 p->rng_fault_state = true;
10616 return WERR_NOT_SUPPORTED;
10619 /****************************************************************
10620 _spoolss_65
10621 ****************************************************************/
10623 WERROR _spoolss_65(struct pipes_struct *p,
10624 struct spoolss_65 *r)
10626 p->rng_fault_state = true;
10627 return WERR_NOT_SUPPORTED;
10630 /****************************************************************
10631 _spoolss_GetCorePrinterDrivers
10632 ****************************************************************/
10634 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
10635 struct spoolss_GetCorePrinterDrivers *r)
10637 p->rng_fault_state = true;
10638 return WERR_NOT_SUPPORTED;
10641 /****************************************************************
10642 _spoolss_67
10643 ****************************************************************/
10645 WERROR _spoolss_67(struct pipes_struct *p,
10646 struct spoolss_67 *r)
10648 p->rng_fault_state = true;
10649 return WERR_NOT_SUPPORTED;
10652 /****************************************************************
10653 _spoolss_GetPrinterDriverPackagePath
10654 ****************************************************************/
10656 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
10657 struct spoolss_GetPrinterDriverPackagePath *r)
10659 p->rng_fault_state = true;
10660 return WERR_NOT_SUPPORTED;
10663 /****************************************************************
10664 _spoolss_69
10665 ****************************************************************/
10667 WERROR _spoolss_69(struct pipes_struct *p,
10668 struct spoolss_69 *r)
10670 p->rng_fault_state = true;
10671 return WERR_NOT_SUPPORTED;
10674 /****************************************************************
10675 _spoolss_6a
10676 ****************************************************************/
10678 WERROR _spoolss_6a(struct pipes_struct *p,
10679 struct spoolss_6a *r)
10681 p->rng_fault_state = true;
10682 return WERR_NOT_SUPPORTED;
10685 /****************************************************************
10686 _spoolss_6b
10687 ****************************************************************/
10689 WERROR _spoolss_6b(struct pipes_struct *p,
10690 struct spoolss_6b *r)
10692 p->rng_fault_state = true;
10693 return WERR_NOT_SUPPORTED;
10696 /****************************************************************
10697 _spoolss_6c
10698 ****************************************************************/
10700 WERROR _spoolss_6c(struct pipes_struct *p,
10701 struct spoolss_6c *r)
10703 p->rng_fault_state = true;
10704 return WERR_NOT_SUPPORTED;
10707 /****************************************************************
10708 _spoolss_6d
10709 ****************************************************************/
10711 WERROR _spoolss_6d(struct pipes_struct *p,
10712 struct spoolss_6d *r)
10714 p->rng_fault_state = true;
10715 return WERR_NOT_SUPPORTED;