s3-spoolss: fix debug statement in spoolss_addprinterex_level_2().
[Samba.git] / source3 / rpc_server / spoolss / srv_spoolss_nt.c
blob312f50965b7ac125a837fc4a7c6f75d371d183a2
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 "nt_printing.h"
32 #include "srv_spoolss_util.h"
33 #include "../librpc/gen_ndr/srv_spoolss.h"
34 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
35 #include "rpc_client/init_spoolss.h"
36 #include "rpc_client/cli_pipe.h"
37 #include "../libcli/security/security.h"
38 #include "librpc/gen_ndr/ndr_security.h"
39 #include "registry.h"
40 #include "registry/reg_objects.h"
41 #include "include/printing.h"
42 #include "secrets.h"
43 #include "../librpc/gen_ndr/netlogon.h"
44 #include "rpc_misc.h"
45 #include "printing/notify.h"
46 #include "serverid.h"
47 #include "../libcli/registry/util_reg.h"
48 #include "smbd/smbd.h"
49 #include "auth.h"
50 #include "messages.h"
51 #include "ntdomain.h"
53 /* macros stolen from s4 spoolss server */
54 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
55 ((info)?ndr_size_##fn(info, level, 0):0)
57 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
58 ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
60 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
61 ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
63 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
65 #undef DBGC_CLASS
66 #define DBGC_CLASS DBGC_RPC_SRV
68 #ifndef MAX_OPEN_PRINTER_EXS
69 #define MAX_OPEN_PRINTER_EXS 50
70 #endif
72 struct notify_back_channel;
74 /* structure to store the printer handles */
75 /* and a reference to what it's pointing to */
76 /* and the notify info asked about */
77 /* that's the central struct */
78 struct printer_handle {
79 struct printer_handle *prev, *next;
80 bool document_started;
81 bool page_started;
82 uint32 jobid; /* jobid in printing backend */
83 int printer_type;
84 const char *servername;
85 fstring sharename;
86 uint32 type;
87 uint32 access_granted;
88 struct {
89 uint32 flags;
90 uint32 options;
91 fstring localmachine;
92 uint32 printerlocal;
93 struct spoolss_NotifyOption *option;
94 struct policy_handle cli_hnd;
95 struct notify_back_channel *cli_chan;
96 uint32 change;
97 /* are we in a FindNextPrinterChangeNotify() call? */
98 bool fnpcn;
99 struct messaging_context *msg_ctx;
100 } notify;
101 struct {
102 fstring machine;
103 fstring user;
104 } client;
106 /* devmode sent in the OpenPrinter() call */
107 struct spoolss_DeviceMode *devmode;
109 /* TODO cache the printer info2 structure */
110 struct spoolss_PrinterInfo2 *info2;
114 static struct printer_handle *printers_list;
116 struct printer_session_counter {
117 struct printer_session_counter *next;
118 struct printer_session_counter *prev;
120 int snum;
121 uint32_t counter;
124 static struct printer_session_counter *counter_list;
126 struct notify_back_channel {
127 struct notify_back_channel *prev, *next;
129 /* associated client */
130 struct sockaddr_storage client_address;
132 /* print notify back-channel pipe handle*/
133 struct rpc_pipe_client *cli_pipe;
134 struct dcerpc_binding_handle *binding_handle;
135 uint32_t active_connections;
138 static struct notify_back_channel *back_channels;
140 /* Map generic permissions to printer object specific permissions */
142 const struct standard_mapping printer_std_mapping = {
143 PRINTER_READ,
144 PRINTER_WRITE,
145 PRINTER_EXECUTE,
146 PRINTER_ALL_ACCESS
149 /* Map generic permissions to print server object specific permissions */
151 const struct standard_mapping printserver_std_mapping = {
152 SERVER_READ,
153 SERVER_WRITE,
154 SERVER_EXECUTE,
155 SERVER_ALL_ACCESS
158 /* API table for Xcv Monitor functions */
160 struct xcv_api_table {
161 const char *name;
162 WERROR(*fn) (TALLOC_CTX *mem_ctx, struct security_token *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
165 static void prune_printername_cache(void);
167 /********************************************************************
168 * Canonicalize servername.
169 ********************************************************************/
171 static const char *canon_servername(const char *servername)
173 const char *pservername = servername;
174 while (*pservername == '\\') {
175 pservername++;
177 return pservername;
180 /* translate between internal status numbers and NT status numbers */
181 static int nt_printj_status(int v)
183 switch (v) {
184 case LPQ_QUEUED:
185 return 0;
186 case LPQ_PAUSED:
187 return JOB_STATUS_PAUSED;
188 case LPQ_SPOOLING:
189 return JOB_STATUS_SPOOLING;
190 case LPQ_PRINTING:
191 return JOB_STATUS_PRINTING;
192 case LPQ_ERROR:
193 return JOB_STATUS_ERROR;
194 case LPQ_DELETING:
195 return JOB_STATUS_DELETING;
196 case LPQ_OFFLINE:
197 return JOB_STATUS_OFFLINE;
198 case LPQ_PAPEROUT:
199 return JOB_STATUS_PAPEROUT;
200 case LPQ_PRINTED:
201 return JOB_STATUS_PRINTED;
202 case LPQ_DELETED:
203 return JOB_STATUS_DELETED;
204 case LPQ_BLOCKED:
205 return JOB_STATUS_BLOCKED_DEVQ;
206 case LPQ_USER_INTERVENTION:
207 return JOB_STATUS_USER_INTERVENTION;
209 return 0;
212 static int nt_printq_status(int v)
214 switch (v) {
215 case LPQ_PAUSED:
216 return PRINTER_STATUS_PAUSED;
217 case LPQ_QUEUED:
218 case LPQ_SPOOLING:
219 case LPQ_PRINTING:
220 return 0;
222 return 0;
225 /***************************************************************************
226 Disconnect from the client
227 ****************************************************************************/
229 static void srv_spoolss_replycloseprinter(int snum,
230 struct printer_handle *prn_hnd)
232 WERROR result;
233 NTSTATUS status;
236 * Tell the specific printing tdb we no longer want messages for this printer
237 * by deregistering our PID.
240 if (!print_notify_deregister_pid(snum)) {
241 DEBUG(0, ("Failed to register our pid for printer %s\n",
242 lp_const_servicename(snum)));
245 /* weird if the test succeeds !!! */
246 if (prn_hnd->notify.cli_chan == NULL ||
247 prn_hnd->notify.cli_chan->active_connections == 0) {
248 DEBUG(0, ("Trying to close unexisting backchannel!\n"));
249 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
250 TALLOC_FREE(prn_hnd->notify.cli_chan);
251 return;
254 status = dcerpc_spoolss_ReplyClosePrinter(
255 prn_hnd->notify.cli_chan->binding_handle,
256 talloc_tos(),
257 &prn_hnd->notify.cli_hnd,
258 &result);
259 if (!NT_STATUS_IS_OK(status)) {
260 DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
261 nt_errstr(status)));
262 result = ntstatus_to_werror(status);
263 } else if (!W_ERROR_IS_OK(result)) {
264 DEBUG(0, ("reply_close_printer failed [%s].\n",
265 win_errstr(result)));
268 /* if it's the last connection, deconnect the IPC$ share */
269 if (prn_hnd->notify.cli_chan->active_connections == 1) {
271 prn_hnd->notify.cli_chan->binding_handle = NULL;
272 cli_shutdown(rpc_pipe_np_smb_conn(prn_hnd->notify.cli_chan->cli_pipe));
273 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
274 TALLOC_FREE(prn_hnd->notify.cli_chan);
276 if (prn_hnd->notify.msg_ctx != NULL) {
277 messaging_deregister(prn_hnd->notify.msg_ctx,
278 MSG_PRINTER_NOTIFY2, NULL);
281 * Tell the serverid.tdb we're no longer
282 * interested in printer notify messages.
285 serverid_register_msg_flags(
286 messaging_server_id(prn_hnd->notify.msg_ctx),
287 false, FLAG_MSG_PRINT_NOTIFY);
291 if (prn_hnd->notify.cli_chan) {
292 prn_hnd->notify.cli_chan->active_connections--;
296 /****************************************************************************
297 Functions to free a printer entry datastruct.
298 ****************************************************************************/
300 static int printer_entry_destructor(struct printer_handle *Printer)
302 if (Printer->notify.cli_chan != NULL &&
303 Printer->notify.cli_chan->active_connections > 0) {
304 int snum = -1;
306 switch(Printer->printer_type) {
307 case SPLHND_SERVER:
308 srv_spoolss_replycloseprinter(snum, Printer);
309 break;
311 case SPLHND_PRINTER:
312 snum = print_queue_snum(Printer->sharename);
313 if (snum != -1) {
314 srv_spoolss_replycloseprinter(snum, Printer);
316 break;
317 default:
318 break;
322 Printer->notify.flags=0;
323 Printer->notify.options=0;
324 Printer->notify.localmachine[0]='\0';
325 Printer->notify.printerlocal=0;
326 TALLOC_FREE(Printer->notify.option);
327 TALLOC_FREE(Printer->devmode);
329 /* Remove from the internal list. */
330 DLIST_REMOVE(printers_list, Printer);
331 return 0;
334 /****************************************************************************
335 find printer index by handle
336 ****************************************************************************/
338 static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
339 struct policy_handle *hnd)
341 struct printer_handle *find_printer = NULL;
343 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
344 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
345 return NULL;
348 return find_printer;
351 /****************************************************************************
352 Close printer index by handle.
353 ****************************************************************************/
355 static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
357 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
359 if (!Printer) {
360 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
361 OUR_HANDLE(hnd)));
362 return false;
365 close_policy_hnd(p, hnd);
367 return true;
370 /****************************************************************************
371 Delete a printer given a handle.
372 ****************************************************************************/
374 static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
375 const char *sharename,
376 struct messaging_context *msg_ctx)
378 char *cmd = lp_deleteprinter_cmd();
379 char *command = NULL;
380 int ret;
381 bool is_print_op = false;
383 /* can't fail if we don't try */
385 if ( !*cmd )
386 return WERR_OK;
388 command = talloc_asprintf(ctx,
389 "%s \"%s\"",
390 cmd, sharename);
391 if (!command) {
392 return WERR_NOMEM;
394 if ( token )
395 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
397 DEBUG(10,("Running [%s]\n", command));
399 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
401 if ( is_print_op )
402 become_root();
404 if ( (ret = smbrun(command, NULL)) == 0 ) {
405 /* Tell everyone we updated smb.conf. */
406 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
409 if ( is_print_op )
410 unbecome_root();
412 /********** END SePrintOperatorPrivlege BLOCK **********/
414 DEBUGADD(10,("returned [%d]\n", ret));
416 TALLOC_FREE(command);
418 if (ret != 0)
419 return WERR_BADFID; /* What to return here? */
421 /* go ahead and re-read the services immediately */
422 become_root();
423 reload_services(msg_ctx, -1, false);
424 unbecome_root();
426 if ( lp_servicenumber( sharename ) >= 0 )
427 return WERR_ACCESS_DENIED;
429 return WERR_OK;
432 /****************************************************************************
433 Delete a printer given a handle.
434 ****************************************************************************/
436 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
438 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
439 WERROR result;
441 if (!Printer) {
442 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
443 OUR_HANDLE(hnd)));
444 return WERR_BADFID;
448 * It turns out that Windows allows delete printer on a handle
449 * opened by an admin user, then used on a pipe handle created
450 * by an anonymous user..... but they're working on security.... riiight !
451 * JRA.
454 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
455 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
456 return WERR_ACCESS_DENIED;
459 /* this does not need a become root since the access check has been
460 done on the handle already */
462 result = winreg_delete_printer_key(p->mem_ctx,
463 get_session_info_system(),
464 p->msg_ctx,
465 Printer->sharename,
466 "");
467 if (!W_ERROR_IS_OK(result)) {
468 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
469 return WERR_BADFID;
472 result = delete_printer_hook(p->mem_ctx, p->session_info->security_token,
473 Printer->sharename, p->msg_ctx);
474 if (!W_ERROR_IS_OK(result)) {
475 return result;
477 prune_printername_cache();
478 return WERR_OK;
481 /****************************************************************************
482 Return the snum of a printer corresponding to an handle.
483 ****************************************************************************/
485 static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
486 int *number, struct share_params **params)
488 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
490 if (!Printer) {
491 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
492 OUR_HANDLE(hnd)));
493 return false;
496 switch (Printer->printer_type) {
497 case SPLHND_PRINTER:
498 DEBUG(4,("short name:%s\n", Printer->sharename));
499 *number = print_queue_snum(Printer->sharename);
500 return (*number != -1);
501 case SPLHND_SERVER:
502 return false;
503 default:
504 return false;
508 /****************************************************************************
509 Set printer handle type.
510 Check if it's \\server or \\server\printer
511 ****************************************************************************/
513 static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
515 DEBUG(3,("Setting printer type=%s\n", handlename));
517 /* it's a print server */
518 if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
519 DEBUGADD(4,("Printer is a print server\n"));
520 Printer->printer_type = SPLHND_SERVER;
522 /* it's a printer (set_printer_hnd_name() will handle port monitors */
523 else {
524 DEBUGADD(4,("Printer is a printer\n"));
525 Printer->printer_type = SPLHND_PRINTER;
528 return true;
531 static void prune_printername_cache_fn(const char *key, const char *value,
532 time_t timeout, void *private_data)
534 gencache_del(key);
537 static void prune_printername_cache(void)
539 gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
542 /****************************************************************************
543 Set printer handle name.. Accept names like \\server, \\server\printer,
544 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
545 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
546 XcvDataPort() interface.
547 ****************************************************************************/
549 static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
550 const struct auth_serversupplied_info *session_info,
551 struct messaging_context *msg_ctx,
552 struct printer_handle *Printer,
553 const char *handlename)
555 int snum;
556 int n_services=lp_numservices();
557 char *aprinter;
558 const char *printername;
559 const char *servername = NULL;
560 fstring sname;
561 bool found = false;
562 struct spoolss_PrinterInfo2 *info2 = NULL;
563 WERROR result;
564 char *p;
567 * Hopefully nobody names his printers like this. Maybe \ or ,
568 * are illegal in printer names even?
570 const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
571 char *cache_key;
572 char *tmp;
574 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
575 (unsigned long)strlen(handlename)));
577 aprinter = CONST_DISCARD(char *, handlename);
578 if ( *handlename == '\\' ) {
579 servername = canon_servername(handlename);
580 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
581 *aprinter = '\0';
582 aprinter++;
584 if (!is_myname_or_ipaddr(servername)) {
585 return WERR_INVALID_PRINTER_NAME;
587 Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
588 if (Printer->servername == NULL) {
589 return WERR_NOMEM;
593 if (Printer->printer_type == SPLHND_SERVER) {
594 return WERR_OK;
597 if (Printer->printer_type != SPLHND_PRINTER) {
598 return WERR_INVALID_HANDLE;
601 DEBUGADD(5, ("searching for [%s]\n", aprinter));
603 p = strchr(aprinter, ',');
604 if (p != NULL) {
605 char *p2 = p;
606 p++;
607 if (*p == ' ') {
608 p++;
610 if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
611 *p2 = '\0';
612 } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
613 *p2 = '\0';
617 if (p) {
618 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
621 /* check for the Port Monitor Interface */
622 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
623 Printer->printer_type = SPLHND_PORTMON_TCP;
624 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
625 found = true;
627 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
628 Printer->printer_type = SPLHND_PORTMON_LOCAL;
629 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
630 found = true;
634 * With hundreds of printers, the "for" loop iterating all
635 * shares can be quite expensive, as it is done on every
636 * OpenPrinter. The loop maps "aprinter" to "sname", the
637 * result of which we cache in gencache.
640 cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s",
641 aprinter);
642 if ((cache_key != NULL) && gencache_get(cache_key, &tmp, NULL)) {
644 found = (strcmp(tmp, printer_not_found) != 0);
645 if (!found) {
646 DEBUG(4, ("Printer %s not found\n", aprinter));
647 SAFE_FREE(tmp);
648 return WERR_INVALID_PRINTER_NAME;
650 fstrcpy(sname, tmp);
651 SAFE_FREE(tmp);
654 /* Search all sharenames first as this is easier than pulling
655 the printer_info_2 off of disk. Don't use find_service() since
656 that calls out to map_username() */
658 /* do another loop to look for printernames */
659 for (snum = 0; !found && snum < n_services; snum++) {
660 const char *printer = lp_const_servicename(snum);
662 /* no point going on if this is not a printer */
663 if (!(lp_snum_ok(snum) && lp_print_ok(snum))) {
664 continue;
667 /* ignore [printers] share */
668 if (strequal(printer, "printers")) {
669 continue;
672 fstrcpy(sname, printer);
673 if (strequal(aprinter, printer)) {
674 found = true;
675 break;
678 /* no point looking up the printer object if
679 we aren't allowing printername != sharename */
680 if (lp_force_printername(snum)) {
681 continue;
684 result = winreg_get_printer(mem_ctx,
685 session_info,
686 msg_ctx,
687 sname,
688 &info2);
689 if ( !W_ERROR_IS_OK(result) ) {
690 DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
691 sname, win_errstr(result)));
692 continue;
695 printername = strrchr(info2->printername, '\\');
696 if (printername == NULL) {
697 printername = info2->printername;
698 } else {
699 printername++;
702 if (strequal(printername, aprinter)) {
703 found = true;
704 break;
707 DEBUGADD(10, ("printername: %s\n", printername));
709 TALLOC_FREE(info2);
712 if ( !found ) {
713 if (cache_key != NULL) {
714 gencache_set(cache_key, printer_not_found,
715 time(NULL)+300);
716 TALLOC_FREE(cache_key);
718 DEBUGADD(4,("Printer not found\n"));
719 return WERR_INVALID_PRINTER_NAME;
722 if (cache_key != NULL) {
723 gencache_set(cache_key, sname, time(NULL)+300);
724 TALLOC_FREE(cache_key);
727 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
729 fstrcpy(Printer->sharename, sname);
731 return WERR_OK;
734 /****************************************************************************
735 Find first available printer slot. creates a printer handle for you.
736 ****************************************************************************/
738 static WERROR open_printer_hnd(struct pipes_struct *p,
739 struct policy_handle *hnd,
740 const char *name,
741 uint32_t access_granted)
743 struct printer_handle *new_printer;
744 WERROR result;
746 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
748 new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
749 if (new_printer == NULL) {
750 return WERR_NOMEM;
752 talloc_set_destructor(new_printer, printer_entry_destructor);
754 /* This also steals the printer_handle on the policy_handle */
755 if (!create_policy_hnd(p, hnd, new_printer)) {
756 TALLOC_FREE(new_printer);
757 return WERR_INVALID_HANDLE;
760 /* Add to the internal list. */
761 DLIST_ADD(printers_list, new_printer);
763 new_printer->notify.option=NULL;
765 if (!set_printer_hnd_printertype(new_printer, name)) {
766 close_printer_handle(p, hnd);
767 return WERR_INVALID_HANDLE;
770 result = set_printer_hnd_name(p->mem_ctx,
771 get_session_info_system(),
772 p->msg_ctx,
773 new_printer, name);
774 if (!W_ERROR_IS_OK(result)) {
775 close_printer_handle(p, hnd);
776 return result;
779 new_printer->access_granted = access_granted;
781 DEBUG(5, ("%d printer handles active\n",
782 (int)num_pipe_handles(p)));
784 return WERR_OK;
787 /***************************************************************************
788 check to see if the client motify handle is monitoring the notification
789 given by (notify_type, notify_field).
790 **************************************************************************/
792 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
793 uint16_t notify_field)
795 return true;
798 static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
799 uint16_t notify_field)
801 struct spoolss_NotifyOption *option = p->notify.option;
802 uint32_t i, j;
805 * Flags should always be zero when the change notify
806 * is registered by the client's spooler. A user Win32 app
807 * might use the flags though instead of the NOTIFY_OPTION_INFO
808 * --jerry
811 if (!option) {
812 return false;
815 if (p->notify.flags)
816 return is_monitoring_event_flags(
817 p->notify.flags, notify_type, notify_field);
819 for (i = 0; i < option->count; i++) {
821 /* Check match for notify_type */
823 if (option->types[i].type != notify_type)
824 continue;
826 /* Check match for field */
828 for (j = 0; j < option->types[i].count; j++) {
829 if (option->types[i].fields[j].field == notify_field) {
830 return true;
835 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
836 p->servername, p->sharename, notify_type, notify_field));
838 return false;
841 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
842 _data->data.integer[0] = _integer; \
843 _data->data.integer[1] = 0;
846 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
847 _data->data.string.string = talloc_strdup(mem_ctx, _p); \
848 if (!_data->data.string.string) {\
849 _data->data.string.size = 0; \
851 _data->data.string.size = strlen_m_term(_p) * 2;
853 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
854 _data->data.devmode.devmode = _devmode;
856 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
857 _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
858 if (!_data->data.sd.sd) { \
859 _data->data.sd.sd_size = 0; \
861 _data->data.sd.sd_size = \
862 ndr_size_security_descriptor(_data->data.sd.sd, 0);
864 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
865 struct tm *t,
866 const char **pp,
867 uint32_t *plen)
869 struct spoolss_Time st;
870 uint32_t len = 16;
871 char *p;
873 if (!init_systemtime(&st, t)) {
874 return;
877 p = talloc_array(mem_ctx, char, len);
878 if (!p) {
879 return;
883 * Systemtime must be linearized as a set of UINT16's.
884 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
887 SSVAL(p, 0, st.year);
888 SSVAL(p, 2, st.month);
889 SSVAL(p, 4, st.day_of_week);
890 SSVAL(p, 6, st.day);
891 SSVAL(p, 8, st.hour);
892 SSVAL(p, 10, st.minute);
893 SSVAL(p, 12, st.second);
894 SSVAL(p, 14, st.millisecond);
896 *pp = p;
897 *plen = len;
900 /* Convert a notification message to a struct spoolss_Notify */
902 static void notify_one_value(struct spoolss_notify_msg *msg,
903 struct spoolss_Notify *data,
904 TALLOC_CTX *mem_ctx)
906 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
909 static void notify_string(struct spoolss_notify_msg *msg,
910 struct spoolss_Notify *data,
911 TALLOC_CTX *mem_ctx)
913 /* The length of the message includes the trailing \0 */
915 data->data.string.size = msg->len * 2;
916 data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
917 if (!data->data.string.string) {
918 data->data.string.size = 0;
919 return;
923 static void notify_system_time(struct spoolss_notify_msg *msg,
924 struct spoolss_Notify *data,
925 TALLOC_CTX *mem_ctx)
927 data->data.string.string = NULL;
928 data->data.string.size = 0;
930 if (msg->len != sizeof(time_t)) {
931 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
932 msg->len));
933 return;
936 init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
937 &data->data.string.string,
938 &data->data.string.size);
941 struct notify2_message_table {
942 const char *name;
943 void (*fn)(struct spoolss_notify_msg *msg,
944 struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
947 static struct notify2_message_table printer_notify_table[] = {
948 /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
949 /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
950 /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
951 /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
952 /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
953 /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
954 /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
955 /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
956 /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
957 /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
958 /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
959 /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
960 /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
961 /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
962 /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
963 /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
964 /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
965 /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
966 /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
969 static struct notify2_message_table job_notify_table[] = {
970 /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
971 /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
972 /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
973 /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
974 /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
975 /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
976 /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
977 /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
978 /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
979 /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
980 /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
981 /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
982 /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
983 /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
984 /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
985 /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
986 /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
987 /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
988 /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
989 /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
990 /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
991 /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
992 /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
993 /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
997 /***********************************************************************
998 Allocate talloc context for container object
999 **********************************************************************/
1001 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1003 if ( !ctr )
1004 return;
1006 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
1008 return;
1011 /***********************************************************************
1012 release all allocated memory and zero out structure
1013 **********************************************************************/
1015 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1017 if ( !ctr )
1018 return;
1020 if ( ctr->ctx )
1021 talloc_destroy(ctr->ctx);
1023 ZERO_STRUCTP(ctr);
1025 return;
1028 /***********************************************************************
1029 **********************************************************************/
1031 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1033 if ( !ctr )
1034 return NULL;
1036 return ctr->ctx;
1039 /***********************************************************************
1040 **********************************************************************/
1042 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1044 if ( !ctr || !ctr->msg_groups )
1045 return NULL;
1047 if ( idx >= ctr->num_groups )
1048 return NULL;
1050 return &ctr->msg_groups[idx];
1054 /***********************************************************************
1055 How many groups of change messages do we have ?
1056 **********************************************************************/
1058 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1060 if ( !ctr )
1061 return 0;
1063 return ctr->num_groups;
1066 /***********************************************************************
1067 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1068 **********************************************************************/
1070 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1072 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
1073 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
1074 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
1075 int i, new_slot;
1077 if ( !ctr || !msg )
1078 return 0;
1080 /* loop over all groups looking for a matching printer name */
1082 for ( i=0; i<ctr->num_groups; i++ ) {
1083 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1084 break;
1087 /* add a new group? */
1089 if ( i == ctr->num_groups ) {
1090 ctr->num_groups++;
1092 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1093 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1094 return 0;
1096 ctr->msg_groups = groups;
1098 /* clear the new entry and set the printer name */
1100 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1101 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1104 /* add the change messages; 'i' is the correct index now regardless */
1106 msg_grp = &ctr->msg_groups[i];
1108 msg_grp->num_msgs++;
1110 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1111 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1112 return 0;
1114 msg_grp->msgs = msg_list;
1116 new_slot = msg_grp->num_msgs-1;
1117 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1119 /* need to allocate own copy of data */
1121 if ( msg->len != 0 )
1122 msg_grp->msgs[new_slot].notify.data = (char *)
1123 TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
1125 return ctr->num_groups;
1128 static void construct_info_data(struct spoolss_Notify *info_data,
1129 enum spoolss_NotifyType type,
1130 uint16_t field, int id);
1132 /***********************************************************************
1133 Send a change notication message on all handles which have a call
1134 back registered
1135 **********************************************************************/
1137 static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1138 struct printer_handle *prn_hnd,
1139 SPOOLSS_NOTIFY_MSG *messages,
1140 uint32_t num_msgs,
1141 struct spoolss_Notify **_notifies,
1142 int *_count)
1144 struct spoolss_Notify *notifies;
1145 SPOOLSS_NOTIFY_MSG *msg;
1146 int count = 0;
1147 uint32_t id;
1148 int i;
1150 notifies = talloc_zero_array(mem_ctx,
1151 struct spoolss_Notify, num_msgs);
1152 if (!notifies) {
1153 return ENOMEM;
1156 for (i = 0; i < num_msgs; i++) {
1158 msg = &messages[i];
1160 /* Are we monitoring this event? */
1162 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1163 continue;
1166 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1167 "for printer [%s]\n",
1168 msg->type, msg->field, prn_hnd->sharename));
1171 * if the is a printer notification handle and not a job
1172 * notification type, then set the id to 0.
1173 * Otherwise just use what was specified in the message.
1175 * When registering change notification on a print server
1176 * handle we always need to send back the id (snum) matching
1177 * the printer for which the change took place.
1178 * For change notify registered on a printer handle,
1179 * this does not matter and the id should be 0.
1181 * --jerry
1184 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1185 (prn_hnd->printer_type == SPLHND_PRINTER)) {
1186 id = 0;
1187 } else {
1188 id = msg->id;
1191 /* Convert unix jobid to smb jobid */
1193 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1194 id = sysjob_to_jobid(msg->id);
1196 if (id == -1) {
1197 DEBUG(3, ("no such unix jobid %d\n",
1198 msg->id));
1199 continue;
1203 construct_info_data(&notifies[count],
1204 msg->type, msg->field, id);
1206 switch(msg->type) {
1207 case PRINTER_NOTIFY_TYPE:
1208 if (printer_notify_table[msg->field].fn) {
1209 printer_notify_table[msg->field].fn(msg,
1210 &notifies[count], mem_ctx);
1212 break;
1214 case JOB_NOTIFY_TYPE:
1215 if (job_notify_table[msg->field].fn) {
1216 job_notify_table[msg->field].fn(msg,
1217 &notifies[count], mem_ctx);
1219 break;
1221 default:
1222 DEBUG(5, ("Unknown notification type %d\n",
1223 msg->type));
1224 continue;
1227 count++;
1230 *_notifies = notifies;
1231 *_count = count;
1233 return 0;
1236 static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1237 struct printer_handle *prn_hnd,
1238 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1240 struct spoolss_Notify *notifies;
1241 int count = 0;
1242 union spoolss_ReplyPrinterInfo info;
1243 struct spoolss_NotifyInfo info0;
1244 uint32_t reply_result;
1245 NTSTATUS status;
1246 WERROR werr;
1247 int ret;
1249 /* Is there notification on this handle? */
1250 if (prn_hnd->notify.cli_chan == NULL ||
1251 prn_hnd->notify.cli_chan->active_connections == 0) {
1252 return 0;
1255 DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1256 prn_hnd->servername, prn_hnd->sharename));
1258 /* For this printer? Print servers always receive notifications. */
1259 if ((prn_hnd->printer_type == SPLHND_PRINTER) &&
1260 (!strequal(msg_group->printername, prn_hnd->sharename))) {
1261 return 0;
1264 DEBUG(10,("Our printer\n"));
1266 /* build the array of change notifications */
1267 ret = build_notify2_messages(mem_ctx, prn_hnd,
1268 msg_group->msgs,
1269 msg_group->num_msgs,
1270 &notifies, &count);
1271 if (ret) {
1272 return ret;
1275 info0.version = 0x2;
1276 info0.flags = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1277 info0.count = count;
1278 info0.notifies = notifies;
1280 info.info0 = &info0;
1282 status = dcerpc_spoolss_RouterReplyPrinterEx(
1283 prn_hnd->notify.cli_chan->binding_handle,
1284 mem_ctx,
1285 &prn_hnd->notify.cli_hnd,
1286 prn_hnd->notify.change, /* color */
1287 prn_hnd->notify.flags,
1288 &reply_result,
1289 0, /* reply_type, must be 0 */
1290 info, &werr);
1291 if (!NT_STATUS_IS_OK(status)) {
1292 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1293 "failed: %s\n",
1294 prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1295 nt_errstr(status)));
1296 werr = ntstatus_to_werror(status);
1297 } else if (!W_ERROR_IS_OK(werr)) {
1298 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1299 "failed: %s\n",
1300 prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1301 win_errstr(werr)));
1303 switch (reply_result) {
1304 case 0:
1305 break;
1306 case PRINTER_NOTIFY_INFO_DISCARDED:
1307 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1308 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1309 break;
1310 default:
1311 break;
1314 return 0;
1317 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1319 struct printer_handle *p;
1320 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
1321 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1322 int ret;
1324 if ( !msg_group ) {
1325 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1326 return;
1329 if (!msg_group->msgs) {
1330 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1331 return;
1334 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1336 /* loop over all printers */
1338 for (p = printers_list; p; p = p->next) {
1339 ret = send_notify2_printer(mem_ctx, p, msg_group);
1340 if (ret) {
1341 goto done;
1345 done:
1346 DEBUG(8,("send_notify2_changes: Exit...\n"));
1347 return;
1350 /***********************************************************************
1351 **********************************************************************/
1353 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1356 uint32_t tv_sec, tv_usec;
1357 size_t offset = 0;
1359 /* Unpack message */
1361 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1362 msg->printer);
1364 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1365 &tv_sec, &tv_usec,
1366 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1368 if (msg->len == 0)
1369 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1370 &msg->notify.value[0], &msg->notify.value[1]);
1371 else
1372 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1373 &msg->len, &msg->notify.data);
1375 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1376 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1378 tv->tv_sec = tv_sec;
1379 tv->tv_usec = tv_usec;
1381 if (msg->len == 0)
1382 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1383 msg->notify.value[1]));
1384 else
1385 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1387 return true;
1390 /********************************************************************
1391 Receive a notify2 message list
1392 ********************************************************************/
1394 static void receive_notify2_message_list(struct messaging_context *msg,
1395 void *private_data,
1396 uint32_t msg_type,
1397 struct server_id server_id,
1398 DATA_BLOB *data)
1400 size_t msg_count, i;
1401 char *buf = (char *)data->data;
1402 char *msg_ptr;
1403 size_t msg_len;
1404 SPOOLSS_NOTIFY_MSG notify;
1405 SPOOLSS_NOTIFY_MSG_CTR messages;
1406 int num_groups;
1408 if (data->length < 4) {
1409 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1410 return;
1413 msg_count = IVAL(buf, 0);
1414 msg_ptr = buf + 4;
1416 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1418 if (msg_count == 0) {
1419 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1420 return;
1423 /* initialize the container */
1425 ZERO_STRUCT( messages );
1426 notify_msg_ctr_init( &messages );
1429 * build message groups for each printer identified
1430 * in a change_notify msg. Remember that a PCN message
1431 * includes the handle returned for the srv_spoolss_replyopenprinter()
1432 * call. Therefore messages are grouped according to printer handle.
1435 for ( i=0; i<msg_count; i++ ) {
1436 struct timeval msg_tv;
1438 if (msg_ptr + 4 - buf > data->length) {
1439 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1440 return;
1443 msg_len = IVAL(msg_ptr,0);
1444 msg_ptr += 4;
1446 if (msg_ptr + msg_len - buf > data->length) {
1447 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1448 return;
1451 /* unpack messages */
1453 ZERO_STRUCT( notify );
1454 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1455 msg_ptr += msg_len;
1457 /* add to correct list in container */
1459 notify_msg_ctr_addmsg( &messages, &notify );
1461 /* free memory that might have been allocated by notify2_unpack_msg() */
1463 if ( notify.len != 0 )
1464 SAFE_FREE( notify.notify.data );
1467 /* process each group of messages */
1469 num_groups = notify_msg_ctr_numgroups( &messages );
1470 for ( i=0; i<num_groups; i++ )
1471 send_notify2_changes( &messages, i );
1474 /* cleanup */
1476 DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1477 (uint32_t)msg_count ));
1479 notify_msg_ctr_destroy( &messages );
1481 return;
1484 /********************************************************************
1485 Send a message to ourself about new driver being installed
1486 so we can upgrade the information for each printer bound to this
1487 driver
1488 ********************************************************************/
1490 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1491 struct messaging_context *msg_ctx)
1493 int len = strlen(drivername);
1495 if (!len)
1496 return false;
1498 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1499 drivername));
1501 messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1502 MSG_PRINTER_DRVUPGRADE,
1503 (uint8_t *)drivername, len+1);
1505 return true;
1508 void srv_spoolss_cleanup(void)
1510 struct printer_session_counter *session_counter;
1512 for (session_counter = counter_list;
1513 session_counter != NULL;
1514 session_counter = counter_list) {
1515 DLIST_REMOVE(counter_list, session_counter);
1516 TALLOC_FREE(session_counter);
1520 /**********************************************************************
1521 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1522 over all printers, upgrading ones as necessary
1523 **********************************************************************/
1525 void do_drv_upgrade_printer(struct messaging_context *msg,
1526 void *private_data,
1527 uint32_t msg_type,
1528 struct server_id server_id,
1529 DATA_BLOB *data)
1531 TALLOC_CTX *tmp_ctx;
1532 struct auth_serversupplied_info *session_info = NULL;
1533 struct spoolss_PrinterInfo2 *pinfo2;
1534 NTSTATUS status;
1535 WERROR result;
1536 const char *drivername;
1537 int snum;
1538 int n_services = lp_numservices();
1540 tmp_ctx = talloc_new(NULL);
1541 if (!tmp_ctx) return;
1543 status = make_session_info_system(tmp_ctx, &session_info);
1544 if (!NT_STATUS_IS_OK(status)) {
1545 DEBUG(0, ("do_drv_upgrade_printer: "
1546 "Could not create system session_info\n"));
1547 goto done;
1550 drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1551 if (!drivername) {
1552 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1553 goto done;
1556 DEBUG(10, ("do_drv_upgrade_printer: "
1557 "Got message for new driver [%s]\n", drivername));
1559 /* Iterate the printer list */
1561 for (snum = 0; snum < n_services; snum++) {
1562 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1563 continue;
1566 /* ignore [printers] share */
1567 if (strequal(lp_const_servicename(snum), "printers")) {
1568 continue;
1571 result = winreg_get_printer(tmp_ctx, session_info, msg,
1572 lp_const_servicename(snum),
1573 &pinfo2);
1575 if (!W_ERROR_IS_OK(result)) {
1576 continue;
1579 if (!pinfo2->drivername) {
1580 continue;
1583 if (strcmp(drivername, pinfo2->drivername) != 0) {
1584 continue;
1587 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1589 /* all we care about currently is the change_id */
1590 result = winreg_printer_update_changeid(tmp_ctx,
1591 session_info,
1592 msg,
1593 pinfo2->printername);
1595 if (!W_ERROR_IS_OK(result)) {
1596 DEBUG(3, ("do_drv_upgrade_printer: "
1597 "Failed to update changeid [%s]\n",
1598 win_errstr(result)));
1602 /* all done */
1603 done:
1604 talloc_free(tmp_ctx);
1607 /********************************************************************
1608 Update the cache for all printq's with a registered client
1609 connection
1610 ********************************************************************/
1612 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1614 struct printer_handle *printer = printers_list;
1615 int snum;
1617 /* loop through all printers and update the cache where
1618 a client is connected */
1619 while (printer) {
1620 if ((printer->printer_type == SPLHND_PRINTER) &&
1621 ((printer->notify.cli_chan != NULL) &&
1622 (printer->notify.cli_chan->active_connections > 0))) {
1623 snum = print_queue_snum(printer->sharename);
1624 print_queue_status(msg_ctx, snum, NULL, NULL);
1627 printer = printer->next;
1630 return;
1633 /****************************************************************
1634 _spoolss_OpenPrinter
1635 ****************************************************************/
1637 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1638 struct spoolss_OpenPrinter *r)
1640 struct spoolss_OpenPrinterEx e;
1641 WERROR werr;
1643 ZERO_STRUCT(e.in.userlevel);
1645 e.in.printername = r->in.printername;
1646 e.in.datatype = r->in.datatype;
1647 e.in.devmode_ctr = r->in.devmode_ctr;
1648 e.in.access_mask = r->in.access_mask;
1649 e.in.level = 0;
1651 e.out.handle = r->out.handle;
1653 werr = _spoolss_OpenPrinterEx(p, &e);
1655 if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1656 /* OpenPrinterEx returns this for a bad
1657 * printer name. We must return WERR_INVALID_PRINTER_NAME
1658 * instead.
1660 werr = WERR_INVALID_PRINTER_NAME;
1663 return werr;
1666 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1667 struct spoolss_DeviceMode *orig,
1668 struct spoolss_DeviceMode **dest)
1670 struct spoolss_DeviceMode *dm;
1672 dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1673 if (!dm) {
1674 return WERR_NOMEM;
1677 /* copy all values, then duplicate strings and structs */
1678 *dm = *orig;
1680 dm->devicename = talloc_strdup(dm, orig->devicename);
1681 if (!dm->devicename) {
1682 return WERR_NOMEM;
1684 dm->formname = talloc_strdup(dm, orig->formname);
1685 if (!dm->formname) {
1686 return WERR_NOMEM;
1688 if (orig->driverextra_data.data) {
1689 dm->driverextra_data.data =
1690 (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1691 orig->driverextra_data.length);
1692 if (!dm->driverextra_data.data) {
1693 return WERR_NOMEM;
1697 *dest = dm;
1698 return WERR_OK;
1701 /****************************************************************
1702 _spoolss_OpenPrinterEx
1703 ****************************************************************/
1705 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1706 struct spoolss_OpenPrinterEx *r)
1708 int snum;
1709 struct printer_handle *Printer=NULL;
1710 WERROR result;
1712 if (!r->in.printername) {
1713 return WERR_INVALID_PARAM;
1716 if (r->in.level > 3) {
1717 return WERR_INVALID_PARAM;
1719 if ((r->in.level == 1 && !r->in.userlevel.level1) ||
1720 (r->in.level == 2 && !r->in.userlevel.level2) ||
1721 (r->in.level == 3 && !r->in.userlevel.level3)) {
1722 return WERR_INVALID_PARAM;
1725 /* some sanity check because you can open a printer or a print server */
1726 /* aka: \\server\printer or \\server */
1728 DEBUGADD(3,("checking name: %s\n", r->in.printername));
1730 result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1731 if (!W_ERROR_IS_OK(result)) {
1732 DEBUG(0,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1733 "for printer %s\n", r->in.printername));
1734 ZERO_STRUCTP(r->out.handle);
1735 return result;
1738 Printer = find_printer_index_by_hnd(p, r->out.handle);
1739 if ( !Printer ) {
1740 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1741 "handle we created for printer %s\n", r->in.printername));
1742 close_printer_handle(p, r->out.handle);
1743 ZERO_STRUCTP(r->out.handle);
1744 return WERR_INVALID_PARAM;
1748 * First case: the user is opening the print server:
1750 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1751 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1753 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1754 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1755 * or if the user is listed in the smb.conf printer admin parameter.
1757 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1758 * client view printer folder, but does not show the MSAPW.
1760 * Note: this test needs code to check access rights here too. Jeremy
1761 * could you look at this?
1763 * Second case: the user is opening a printer:
1764 * NT doesn't let us connect to a printer if the connecting user
1765 * doesn't have print permission.
1767 * Third case: user is opening a Port Monitor
1768 * access checks same as opening a handle to the print server.
1771 switch (Printer->printer_type )
1773 case SPLHND_SERVER:
1774 case SPLHND_PORTMON_TCP:
1775 case SPLHND_PORTMON_LOCAL:
1776 /* Printserver handles use global struct... */
1778 snum = -1;
1780 /* Map standard access rights to object specific access rights */
1782 se_map_standard(&r->in.access_mask,
1783 &printserver_std_mapping);
1785 /* Deny any object specific bits that don't apply to print
1786 servers (i.e printer and job specific bits) */
1788 r->in.access_mask &= SEC_MASK_SPECIFIC;
1790 if (r->in.access_mask &
1791 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1792 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1793 close_printer_handle(p, r->out.handle);
1794 ZERO_STRUCTP(r->out.handle);
1795 return WERR_ACCESS_DENIED;
1798 /* Allow admin access */
1800 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1802 if (!lp_ms_add_printer_wizard()) {
1803 close_printer_handle(p, r->out.handle);
1804 ZERO_STRUCTP(r->out.handle);
1805 return WERR_ACCESS_DENIED;
1808 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1809 and not a printer admin, then fail */
1811 if ((p->session_info->utok.uid != sec_initial_uid()) &&
1812 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
1813 !nt_token_check_sid(&global_sid_Builtin_Print_Operators, p->session_info->security_token) &&
1814 !token_contains_name_in_list(
1815 uidtoname(p->session_info->utok.uid),
1816 p->session_info->info3->base.domain.string,
1817 NULL,
1818 p->session_info->security_token,
1819 lp_printer_admin(snum))) {
1820 close_printer_handle(p, r->out.handle);
1821 ZERO_STRUCTP(r->out.handle);
1822 DEBUG(3,("access DENIED as user is not root, "
1823 "has no printoperator privilege, "
1824 "not a member of the printoperator builtin group and "
1825 "is not in printer admin list"));
1826 return WERR_ACCESS_DENIED;
1829 r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1831 else
1833 r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1836 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1837 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1839 /* We fall through to return WERR_OK */
1840 break;
1842 case SPLHND_PRINTER:
1843 /* NT doesn't let us connect to a printer if the connecting user
1844 doesn't have print permission. */
1846 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1847 close_printer_handle(p, r->out.handle);
1848 ZERO_STRUCTP(r->out.handle);
1849 return WERR_BADFID;
1852 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1853 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1856 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1858 /* map an empty access mask to the minimum access mask */
1859 if (r->in.access_mask == 0x0)
1860 r->in.access_mask = PRINTER_ACCESS_USE;
1863 * If we are not serving the printer driver for this printer,
1864 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1865 * will keep NT clients happy --jerry
1868 if (lp_use_client_driver(snum)
1869 && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1871 r->in.access_mask = PRINTER_ACCESS_USE;
1874 /* check smb.conf parameters and the the sec_desc */
1876 if (!allow_access(lp_hostsdeny(snum), lp_hostsallow(snum),
1877 p->client_id->name, p->client_id->addr)) {
1878 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1879 ZERO_STRUCTP(r->out.handle);
1880 return WERR_ACCESS_DENIED;
1883 if (!user_ok_token(uidtoname(p->session_info->utok.uid), NULL,
1884 p->session_info->security_token, snum) ||
1885 !print_access_check(p->session_info,
1886 p->msg_ctx,
1887 snum,
1888 r->in.access_mask)) {
1889 DEBUG(3, ("access DENIED for printer open\n"));
1890 close_printer_handle(p, r->out.handle);
1891 ZERO_STRUCTP(r->out.handle);
1892 return WERR_ACCESS_DENIED;
1895 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1896 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1897 close_printer_handle(p, r->out.handle);
1898 ZERO_STRUCTP(r->out.handle);
1899 return WERR_ACCESS_DENIED;
1902 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1903 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1904 else
1905 r->in.access_mask = PRINTER_ACCESS_USE;
1907 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1908 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1910 winreg_create_printer(p->mem_ctx,
1911 get_session_info_system(),
1912 p->msg_ctx,
1913 lp_const_servicename(snum));
1915 break;
1917 default:
1918 /* sanity check to prevent programmer error */
1919 ZERO_STRUCTP(r->out.handle);
1920 return WERR_BADFID;
1923 Printer->access_granted = r->in.access_mask;
1926 * If the client sent a devmode in the OpenPrinter() call, then
1927 * save it here in case we get a job submission on this handle
1930 if ((Printer->printer_type != SPLHND_SERVER) &&
1931 r->in.devmode_ctr.devmode) {
1932 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1933 &Printer->devmode);
1936 #if 0 /* JERRY -- I'm doubtful this is really effective */
1937 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1938 optimization in Windows 2000 clients --jerry */
1940 if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1941 && (RA_WIN2K == get_remote_arch()) )
1943 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1944 sys_usleep( 500000 );
1946 #endif
1948 return WERR_OK;
1951 /****************************************************************
1952 _spoolss_ClosePrinter
1953 ****************************************************************/
1955 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1956 struct spoolss_ClosePrinter *r)
1958 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1960 if (Printer && Printer->document_started) {
1961 struct spoolss_EndDocPrinter e;
1963 e.in.handle = r->in.handle;
1965 _spoolss_EndDocPrinter(p, &e);
1968 if (!close_printer_handle(p, r->in.handle))
1969 return WERR_BADFID;
1971 /* clear the returned printer handle. Observed behavior
1972 from Win2k server. Don't think this really matters.
1973 Previous code just copied the value of the closed
1974 handle. --jerry */
1976 ZERO_STRUCTP(r->out.handle);
1978 return WERR_OK;
1981 /****************************************************************
1982 _spoolss_DeletePrinter
1983 ****************************************************************/
1985 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
1986 struct spoolss_DeletePrinter *r)
1988 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1989 WERROR result;
1990 int snum;
1992 if (Printer && Printer->document_started) {
1993 struct spoolss_EndDocPrinter e;
1995 e.in.handle = r->in.handle;
1997 _spoolss_EndDocPrinter(p, &e);
2000 if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
2001 winreg_delete_printer_key(p->mem_ctx,
2002 get_session_info_system(),
2003 p->msg_ctx,
2004 lp_const_servicename(snum),
2005 "");
2008 result = delete_printer_handle(p, r->in.handle);
2010 return result;
2013 /*******************************************************************
2014 * static function to lookup the version id corresponding to an
2015 * long architecture string
2016 ******************************************************************/
2018 static const struct print_architecture_table_node archi_table[]= {
2020 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
2021 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
2022 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
2023 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
2024 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
2025 {"Windows IA64", SPL_ARCH_IA64, 3 },
2026 {"Windows x64", SPL_ARCH_X64, 3 },
2027 {NULL, "", -1 }
2030 static int get_version_id(const char *arch)
2032 int i;
2034 for (i=0; archi_table[i].long_archi != NULL; i++)
2036 if (strcmp(arch, archi_table[i].long_archi) == 0)
2037 return (archi_table[i].version);
2040 return -1;
2043 /****************************************************************
2044 _spoolss_DeletePrinterDriver
2045 ****************************************************************/
2047 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2048 struct spoolss_DeletePrinterDriver *r)
2051 struct spoolss_DriverInfo8 *info = NULL;
2052 struct spoolss_DriverInfo8 *info_win2k = NULL;
2053 int version;
2054 WERROR status;
2056 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2057 and not a printer admin, then fail */
2059 if ( (p->session_info->utok.uid != sec_initial_uid())
2060 && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2061 && !token_contains_name_in_list(
2062 uidtoname(p->session_info->utok.uid),
2063 p->session_info->info3->base.domain.string,
2064 NULL,
2065 p->session_info->security_token,
2066 lp_printer_admin(-1)) )
2068 return WERR_ACCESS_DENIED;
2071 /* check that we have a valid driver name first */
2073 if ((version = get_version_id(r->in.architecture)) == -1)
2074 return WERR_INVALID_ENVIRONMENT;
2076 status = winreg_get_driver(p->mem_ctx,
2077 get_session_info_system(),
2078 p->msg_ctx,
2079 r->in.architecture, r->in.driver,
2080 version, &info);
2081 if (!W_ERROR_IS_OK(status)) {
2082 /* try for Win2k driver if "Windows NT x86" */
2084 if ( version == 2 ) {
2085 version = 3;
2087 status = winreg_get_driver(p->mem_ctx,
2088 get_session_info_system(),
2089 p->msg_ctx,
2090 r->in.architecture,
2091 r->in.driver,
2092 version, &info);
2093 if (!W_ERROR_IS_OK(status)) {
2094 status = WERR_UNKNOWN_PRINTER_DRIVER;
2095 goto done;
2098 /* otherwise it was a failure */
2099 else {
2100 status = WERR_UNKNOWN_PRINTER_DRIVER;
2101 goto done;
2106 if (printer_driver_in_use(p->mem_ctx,
2107 get_session_info_system(),
2108 p->msg_ctx,
2109 info)) {
2110 status = WERR_PRINTER_DRIVER_IN_USE;
2111 goto done;
2114 if (version == 2) {
2115 status = winreg_get_driver(p->mem_ctx,
2116 get_session_info_system(),
2117 p->msg_ctx,
2118 r->in.architecture,
2119 r->in.driver, 3, &info_win2k);
2120 if (W_ERROR_IS_OK(status)) {
2121 /* if we get to here, we now have 2 driver info structures to remove */
2122 /* remove the Win2k driver first*/
2124 status = winreg_del_driver(p->mem_ctx,
2125 get_session_info_system(),
2126 p->msg_ctx,
2127 info_win2k, 3);
2128 talloc_free(info_win2k);
2130 /* this should not have failed---if it did, report to client */
2131 if (!W_ERROR_IS_OK(status)) {
2132 goto done;
2137 status = winreg_del_driver(p->mem_ctx,
2138 get_session_info_system(),
2139 p->msg_ctx,
2140 info, version);
2142 done:
2143 talloc_free(info);
2145 return status;
2148 /****************************************************************
2149 _spoolss_DeletePrinterDriverEx
2150 ****************************************************************/
2152 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2153 struct spoolss_DeletePrinterDriverEx *r)
2155 struct spoolss_DriverInfo8 *info = NULL;
2156 struct spoolss_DriverInfo8 *info_win2k = NULL;
2157 int version;
2158 bool delete_files;
2159 WERROR status;
2161 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2162 and not a printer admin, then fail */
2164 if ( (p->session_info->utok.uid != sec_initial_uid())
2165 && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2166 && !token_contains_name_in_list(
2167 uidtoname(p->session_info->utok.uid),
2168 p->session_info->info3->base.domain.string,
2169 NULL,
2170 p->session_info->security_token, lp_printer_admin(-1)) )
2172 return WERR_ACCESS_DENIED;
2175 /* check that we have a valid driver name first */
2176 if ((version = get_version_id(r->in.architecture)) == -1) {
2177 /* this is what NT returns */
2178 return WERR_INVALID_ENVIRONMENT;
2181 if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2182 version = r->in.version;
2184 status = winreg_get_driver(p->mem_ctx,
2185 get_session_info_system(),
2186 p->msg_ctx,
2187 r->in.architecture,
2188 r->in.driver,
2189 version,
2190 &info);
2191 if (!W_ERROR_IS_OK(status)) {
2192 status = WERR_UNKNOWN_PRINTER_DRIVER;
2195 * if the client asked for a specific version,
2196 * or this is something other than Windows NT x86,
2197 * then we've failed
2200 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2201 goto done;
2203 /* try for Win2k driver if "Windows NT x86" */
2205 version = 3;
2206 status = winreg_get_driver(info,
2207 get_session_info_system(),
2208 p->msg_ctx,
2209 r->in.architecture,
2210 r->in.driver,
2211 version, &info);
2212 if (!W_ERROR_IS_OK(status)) {
2213 status = WERR_UNKNOWN_PRINTER_DRIVER;
2214 goto done;
2218 if (printer_driver_in_use(info,
2219 get_session_info_system(),
2220 p->msg_ctx,
2221 info)) {
2222 status = WERR_PRINTER_DRIVER_IN_USE;
2223 goto done;
2227 * we have a couple of cases to consider.
2228 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2229 * then the delete should fail if **any** files overlap with
2230 * other drivers
2231 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2232 * non-overlapping files
2233 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2234 * is set, the do not delete any files
2235 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2238 delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2240 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2242 if (delete_files &&
2243 (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2244 printer_driver_files_in_use(info,
2245 get_session_info_system(),
2246 p->msg_ctx,
2247 info)) {
2248 /* no idea of the correct error here */
2249 status = WERR_ACCESS_DENIED;
2250 goto done;
2254 /* also check for W32X86/3 if necessary; maybe we already have? */
2256 if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2257 status = winreg_get_driver(info,
2258 get_session_info_system(),
2259 p->msg_ctx,
2260 r->in.architecture,
2261 r->in.driver, 3, &info_win2k);
2262 if (W_ERROR_IS_OK(status)) {
2264 if (delete_files &&
2265 (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2266 printer_driver_files_in_use(info,
2267 get_session_info_system(),
2268 p->msg_ctx,
2269 info_win2k)) {
2270 /* no idea of the correct error here */
2271 talloc_free(info_win2k);
2272 status = WERR_ACCESS_DENIED;
2273 goto done;
2276 /* if we get to here, we now have 2 driver info structures to remove */
2277 /* remove the Win2k driver first*/
2279 status = winreg_del_driver(info,
2280 get_session_info_system(),
2281 p->msg_ctx,
2282 info_win2k,
2285 /* this should not have failed---if it did, report to client */
2287 if (!W_ERROR_IS_OK(status)) {
2288 goto done;
2292 * now delete any associated files if delete_files is
2293 * true. Even if this part failes, we return succes
2294 * because the driver doesn not exist any more
2296 if (delete_files) {
2297 delete_driver_files(get_session_info_system(),
2298 info_win2k);
2303 status = winreg_del_driver(info,
2304 get_session_info_system(),
2305 p->msg_ctx,
2306 info,
2307 version);
2308 if (!W_ERROR_IS_OK(status)) {
2309 goto done;
2313 * now delete any associated files if delete_files is
2314 * true. Even if this part failes, we return succes
2315 * because the driver doesn not exist any more
2317 if (delete_files) {
2318 delete_driver_files(get_session_info_system(), info);
2321 done:
2322 talloc_free(info);
2323 return status;
2327 /********************************************************************
2328 GetPrinterData on a printer server Handle.
2329 ********************************************************************/
2331 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2332 const char *value,
2333 enum winreg_Type *type,
2334 union spoolss_PrinterData *data)
2336 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2338 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2339 *type = REG_DWORD;
2340 data->value = 0x00;
2341 return WERR_OK;
2344 if (!StrCaseCmp(value, "BeepEnabled")) {
2345 *type = REG_DWORD;
2346 data->value = 0x00;
2347 return WERR_OK;
2350 if (!StrCaseCmp(value, "EventLog")) {
2351 *type = REG_DWORD;
2352 /* formally was 0x1b */
2353 data->value = 0x00;
2354 return WERR_OK;
2357 if (!StrCaseCmp(value, "NetPopup")) {
2358 *type = REG_DWORD;
2359 data->value = 0x00;
2360 return WERR_OK;
2363 if (!StrCaseCmp(value, "MajorVersion")) {
2364 *type = REG_DWORD;
2366 /* Windows NT 4.0 seems to not allow uploading of drivers
2367 to a server that reports 0x3 as the MajorVersion.
2368 need to investigate more how Win2k gets around this .
2369 -- jerry */
2371 if (RA_WINNT == get_remote_arch()) {
2372 data->value = 0x02;
2373 } else {
2374 data->value = 0x03;
2377 return WERR_OK;
2380 if (!StrCaseCmp(value, "MinorVersion")) {
2381 *type = REG_DWORD;
2382 data->value = 0x00;
2383 return WERR_OK;
2386 /* REG_BINARY
2387 * uint32_t size = 0x114
2388 * uint32_t major = 5
2389 * uint32_t minor = [0|1]
2390 * uint32_t build = [2195|2600]
2391 * extra unicode string = e.g. "Service Pack 3"
2393 if (!StrCaseCmp(value, "OSVersion")) {
2394 DATA_BLOB blob;
2395 enum ndr_err_code ndr_err;
2396 struct spoolss_OSVersion os;
2398 os.major = 5; /* Windows 2000 == 5.0 */
2399 os.minor = 0;
2400 os.build = 2195; /* build */
2401 os.extra_string = ""; /* leave extra string empty */
2403 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2404 (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2405 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2406 return WERR_GENERAL_FAILURE;
2409 *type = REG_BINARY;
2410 data->binary = blob;
2412 return WERR_OK;
2416 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2417 *type = REG_SZ;
2419 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2420 W_ERROR_HAVE_NO_MEMORY(data->string);
2422 return WERR_OK;
2425 if (!StrCaseCmp(value, "Architecture")) {
2426 *type = REG_SZ;
2427 data->string = talloc_strdup(mem_ctx,
2428 lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2429 W_ERROR_HAVE_NO_MEMORY(data->string);
2431 return WERR_OK;
2434 if (!StrCaseCmp(value, "DsPresent")) {
2435 *type = REG_DWORD;
2437 /* only show the publish check box if we are a
2438 member of a AD domain */
2440 if (lp_security() == SEC_ADS) {
2441 data->value = 0x01;
2442 } else {
2443 data->value = 0x00;
2445 return WERR_OK;
2448 if (!StrCaseCmp(value, "DNSMachineName")) {
2449 const char *hostname = get_mydnsfullname();
2451 if (!hostname) {
2452 return WERR_BADFILE;
2455 *type = REG_SZ;
2456 data->string = talloc_strdup(mem_ctx, hostname);
2457 W_ERROR_HAVE_NO_MEMORY(data->string);
2459 return WERR_OK;
2462 *type = REG_NONE;
2464 return WERR_INVALID_PARAM;
2467 /****************************************************************
2468 _spoolss_GetPrinterData
2469 ****************************************************************/
2471 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2472 struct spoolss_GetPrinterData *r)
2474 struct spoolss_GetPrinterDataEx r2;
2476 r2.in.handle = r->in.handle;
2477 r2.in.key_name = "PrinterDriverData";
2478 r2.in.value_name = r->in.value_name;
2479 r2.in.offered = r->in.offered;
2480 r2.out.type = r->out.type;
2481 r2.out.data = r->out.data;
2482 r2.out.needed = r->out.needed;
2484 return _spoolss_GetPrinterDataEx(p, &r2);
2487 /*********************************************************
2488 Connect to the client machine.
2489 **********************************************************/
2491 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2492 struct sockaddr_storage *client_ss, const char *remote_machine)
2494 NTSTATUS ret;
2495 struct cli_state *the_cli;
2496 struct sockaddr_storage rm_addr;
2497 char addr[INET6_ADDRSTRLEN];
2499 if ( is_zero_addr(client_ss) ) {
2500 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2501 remote_machine));
2502 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2503 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2504 return false;
2506 print_sockaddr(addr, sizeof(addr), &rm_addr);
2507 } else {
2508 rm_addr = *client_ss;
2509 print_sockaddr(addr, sizeof(addr), &rm_addr);
2510 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2511 addr));
2514 if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2515 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2516 addr));
2517 return false;
2520 /* setup the connection */
2521 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2522 &rm_addr, 0, "IPC$", "IPC",
2523 "", /* username */
2524 "", /* domain */
2525 "", /* password */
2526 0, lp_client_signing());
2528 if ( !NT_STATUS_IS_OK( ret ) ) {
2529 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2530 remote_machine ));
2531 return false;
2534 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2535 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2536 cli_shutdown(the_cli);
2537 return false;
2541 * Ok - we have an anonymous connection to the IPC$ share.
2542 * Now start the NT Domain stuff :-).
2545 ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2546 if (!NT_STATUS_IS_OK(ret)) {
2547 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2548 remote_machine, nt_errstr(ret)));
2549 cli_shutdown(the_cli);
2550 return false;
2553 return true;
2556 /***************************************************************************
2557 Connect to the client.
2558 ****************************************************************************/
2560 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2561 uint32_t localprinter,
2562 enum winreg_Type type,
2563 struct policy_handle *handle,
2564 struct notify_back_channel **_chan,
2565 struct sockaddr_storage *client_ss,
2566 struct messaging_context *msg_ctx)
2568 WERROR result;
2569 NTSTATUS status;
2570 struct notify_back_channel *chan;
2572 for (chan = back_channels; chan; chan = chan->next) {
2573 if (memcmp(&chan->client_address, client_ss,
2574 sizeof(struct sockaddr_storage)) == 0) {
2575 break;
2580 * If it's the first connection, contact the client
2581 * and connect to the IPC$ share anonymously
2583 if (!chan) {
2584 fstring unix_printer;
2586 /* the +2 is to strip the leading 2 backslashs */
2587 fstrcpy(unix_printer, printer + 2);
2589 chan = talloc_zero(back_channels, struct notify_back_channel);
2590 if (!chan) {
2591 return false;
2593 chan->client_address = *client_ss;
2595 if (!spoolss_connect_to_client(&chan->cli_pipe, client_ss, unix_printer)) {
2596 TALLOC_FREE(chan);
2597 return false;
2599 chan->binding_handle = chan->cli_pipe->binding_handle;
2601 DLIST_ADD(back_channels, chan);
2603 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2604 receive_notify2_message_list);
2605 /* Tell the connections db we're now interested in printer
2606 * notify messages. */
2607 serverid_register_msg_flags(messaging_server_id(msg_ctx),
2608 true, FLAG_MSG_PRINT_NOTIFY);
2612 * Tell the specific printing tdb we want messages for this printer
2613 * by registering our PID.
2616 if (!print_notify_register_pid(snum)) {
2617 DEBUG(0, ("Failed to register our pid for printer %s\n",
2618 printer));
2621 status = dcerpc_spoolss_ReplyOpenPrinter(chan->binding_handle,
2622 talloc_tos(),
2623 printer,
2624 localprinter,
2625 type,
2627 NULL,
2628 handle,
2629 &result);
2630 if (!NT_STATUS_IS_OK(status)) {
2631 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2632 result = ntstatus_to_werror(status);
2633 } else if (!W_ERROR_IS_OK(result)) {
2634 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2637 chan->active_connections++;
2638 *_chan = chan;
2640 return (W_ERROR_IS_OK(result));
2643 /****************************************************************
2644 ****************************************************************/
2646 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2647 const struct spoolss_NotifyOption *r)
2649 struct spoolss_NotifyOption *option;
2650 uint32_t i,k;
2652 if (!r) {
2653 return NULL;
2656 option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2657 if (!option) {
2658 return NULL;
2661 *option = *r;
2663 if (!option->count) {
2664 return option;
2667 option->types = talloc_zero_array(option,
2668 struct spoolss_NotifyOptionType, option->count);
2669 if (!option->types) {
2670 talloc_free(option);
2671 return NULL;
2674 for (i=0; i < option->count; i++) {
2675 option->types[i] = r->types[i];
2677 if (option->types[i].count) {
2678 option->types[i].fields = talloc_zero_array(option,
2679 union spoolss_Field, option->types[i].count);
2680 if (!option->types[i].fields) {
2681 talloc_free(option);
2682 return NULL;
2684 for (k=0; k<option->types[i].count; k++) {
2685 option->types[i].fields[k] =
2686 r->types[i].fields[k];
2691 return option;
2694 /****************************************************************
2695 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2697 * before replying OK: status=0 a rpc call is made to the workstation
2698 * asking ReplyOpenPrinter
2700 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2701 * called from api_spoolss_rffpcnex
2702 ****************************************************************/
2704 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2705 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2707 int snum = -1;
2708 struct spoolss_NotifyOption *option = r->in.notify_options;
2709 struct sockaddr_storage client_ss;
2711 /* store the notify value in the printer struct */
2713 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2715 if (!Printer) {
2716 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2717 "Invalid handle (%s:%u:%u).\n",
2718 OUR_HANDLE(r->in.handle)));
2719 return WERR_BADFID;
2722 Printer->notify.flags = r->in.flags;
2723 Printer->notify.options = r->in.options;
2724 Printer->notify.printerlocal = r->in.printer_local;
2725 Printer->notify.msg_ctx = p->msg_ctx;
2727 TALLOC_FREE(Printer->notify.option);
2728 Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2730 fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2732 /* Connect to the client machine and send a ReplyOpenPrinter */
2734 if ( Printer->printer_type == SPLHND_SERVER)
2735 snum = -1;
2736 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2737 !get_printer_snum(p, r->in.handle, &snum, NULL) )
2738 return WERR_BADFID;
2740 DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2741 "client_address is %s\n", p->client_id->addr));
2743 if (!lp_print_notify_backchannel(snum)) {
2744 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2745 "backchannel disabled\n"));
2746 return WERR_SERVER_UNAVAILABLE;
2749 if (!interpret_string_addr(&client_ss, p->client_id->addr,
2750 AI_NUMERICHOST)) {
2751 return WERR_SERVER_UNAVAILABLE;
2754 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2755 Printer->notify.printerlocal, REG_SZ,
2756 &Printer->notify.cli_hnd,
2757 &Printer->notify.cli_chan,
2758 &client_ss, p->msg_ctx)) {
2759 return WERR_SERVER_UNAVAILABLE;
2762 return WERR_OK;
2765 /*******************************************************************
2766 * fill a notify_info_data with the servername
2767 ********************************************************************/
2769 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2770 int snum,
2771 struct spoolss_Notify *data,
2772 print_queue_struct *queue,
2773 struct spoolss_PrinterInfo2 *pinfo2,
2774 TALLOC_CTX *mem_ctx)
2776 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2779 /*******************************************************************
2780 * fill a notify_info_data with the printername (not including the servername).
2781 ********************************************************************/
2783 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2784 int snum,
2785 struct spoolss_Notify *data,
2786 print_queue_struct *queue,
2787 struct spoolss_PrinterInfo2 *pinfo2,
2788 TALLOC_CTX *mem_ctx)
2790 /* the notify name should not contain the \\server\ part */
2791 const char *p = strrchr(pinfo2->printername, '\\');
2793 if (!p) {
2794 p = pinfo2->printername;
2795 } else {
2796 p++;
2799 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2802 /*******************************************************************
2803 * fill a notify_info_data with the servicename
2804 ********************************************************************/
2806 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2807 int snum,
2808 struct spoolss_Notify *data,
2809 print_queue_struct *queue,
2810 struct spoolss_PrinterInfo2 *pinfo2,
2811 TALLOC_CTX *mem_ctx)
2813 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2816 /*******************************************************************
2817 * fill a notify_info_data with the port name
2818 ********************************************************************/
2820 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2821 int snum,
2822 struct spoolss_Notify *data,
2823 print_queue_struct *queue,
2824 struct spoolss_PrinterInfo2 *pinfo2,
2825 TALLOC_CTX *mem_ctx)
2827 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2830 /*******************************************************************
2831 * fill a notify_info_data with the printername
2832 * but it doesn't exist, have to see what to do
2833 ********************************************************************/
2835 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2836 int snum,
2837 struct spoolss_Notify *data,
2838 print_queue_struct *queue,
2839 struct spoolss_PrinterInfo2 *pinfo2,
2840 TALLOC_CTX *mem_ctx)
2842 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2845 /*******************************************************************
2846 * fill a notify_info_data with the comment
2847 ********************************************************************/
2849 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2850 int snum,
2851 struct spoolss_Notify *data,
2852 print_queue_struct *queue,
2853 struct spoolss_PrinterInfo2 *pinfo2,
2854 TALLOC_CTX *mem_ctx)
2856 const char *p;
2858 if (*pinfo2->comment == '\0') {
2859 p = lp_comment(snum);
2860 } else {
2861 p = pinfo2->comment;
2864 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2867 /*******************************************************************
2868 * fill a notify_info_data with the comment
2869 * location = "Room 1, floor 2, building 3"
2870 ********************************************************************/
2872 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2873 int snum,
2874 struct spoolss_Notify *data,
2875 print_queue_struct *queue,
2876 struct spoolss_PrinterInfo2 *pinfo2,
2877 TALLOC_CTX *mem_ctx)
2879 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->location);
2882 /*******************************************************************
2883 * fill a notify_info_data with the device mode
2884 * jfm:xxxx don't to it for know but that's a real problem !!!
2885 ********************************************************************/
2887 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2888 int snum,
2889 struct spoolss_Notify *data,
2890 print_queue_struct *queue,
2891 struct spoolss_PrinterInfo2 *pinfo2,
2892 TALLOC_CTX *mem_ctx)
2894 /* for a dummy implementation we have to zero the fields */
2895 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2898 /*******************************************************************
2899 * fill a notify_info_data with the separator file name
2900 ********************************************************************/
2902 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2903 int snum,
2904 struct spoolss_Notify *data,
2905 print_queue_struct *queue,
2906 struct spoolss_PrinterInfo2 *pinfo2,
2907 TALLOC_CTX *mem_ctx)
2909 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2912 /*******************************************************************
2913 * fill a notify_info_data with the print processor
2914 * jfm:xxxx return always winprint to indicate we don't do anything to it
2915 ********************************************************************/
2917 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2918 int snum,
2919 struct spoolss_Notify *data,
2920 print_queue_struct *queue,
2921 struct spoolss_PrinterInfo2 *pinfo2,
2922 TALLOC_CTX *mem_ctx)
2924 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2927 /*******************************************************************
2928 * fill a notify_info_data with the print processor options
2929 * jfm:xxxx send an empty string
2930 ********************************************************************/
2932 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2933 int snum,
2934 struct spoolss_Notify *data,
2935 print_queue_struct *queue,
2936 struct spoolss_PrinterInfo2 *pinfo2,
2937 TALLOC_CTX *mem_ctx)
2939 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2942 /*******************************************************************
2943 * fill a notify_info_data with the data type
2944 * jfm:xxxx always send RAW as data type
2945 ********************************************************************/
2947 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2948 int snum,
2949 struct spoolss_Notify *data,
2950 print_queue_struct *queue,
2951 struct spoolss_PrinterInfo2 *pinfo2,
2952 TALLOC_CTX *mem_ctx)
2954 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2957 /*******************************************************************
2958 * fill a notify_info_data with the security descriptor
2959 * jfm:xxxx send an null pointer to say no security desc
2960 * have to implement security before !
2961 ********************************************************************/
2963 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2964 int snum,
2965 struct spoolss_Notify *data,
2966 print_queue_struct *queue,
2967 struct spoolss_PrinterInfo2 *pinfo2,
2968 TALLOC_CTX *mem_ctx)
2970 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
2973 /*******************************************************************
2974 * fill a notify_info_data with the attributes
2975 * jfm:xxxx a samba printer is always shared
2976 ********************************************************************/
2978 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2979 int snum,
2980 struct spoolss_Notify *data,
2981 print_queue_struct *queue,
2982 struct spoolss_PrinterInfo2 *pinfo2,
2983 TALLOC_CTX *mem_ctx)
2985 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2988 /*******************************************************************
2989 * fill a notify_info_data with the priority
2990 ********************************************************************/
2992 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
2993 int snum,
2994 struct spoolss_Notify *data,
2995 print_queue_struct *queue,
2996 struct spoolss_PrinterInfo2 *pinfo2,
2997 TALLOC_CTX *mem_ctx)
2999 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
3002 /*******************************************************************
3003 * fill a notify_info_data with the default priority
3004 ********************************************************************/
3006 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
3007 int snum,
3008 struct spoolss_Notify *data,
3009 print_queue_struct *queue,
3010 struct spoolss_PrinterInfo2 *pinfo2,
3011 TALLOC_CTX *mem_ctx)
3013 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
3016 /*******************************************************************
3017 * fill a notify_info_data with the start time
3018 ********************************************************************/
3020 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
3021 int snum,
3022 struct spoolss_Notify *data,
3023 print_queue_struct *queue,
3024 struct spoolss_PrinterInfo2 *pinfo2,
3025 TALLOC_CTX *mem_ctx)
3027 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3030 /*******************************************************************
3031 * fill a notify_info_data with the until time
3032 ********************************************************************/
3034 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3035 int snum,
3036 struct spoolss_Notify *data,
3037 print_queue_struct *queue,
3038 struct spoolss_PrinterInfo2 *pinfo2,
3039 TALLOC_CTX *mem_ctx)
3041 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3044 /*******************************************************************
3045 * fill a notify_info_data with the status
3046 ********************************************************************/
3048 static void spoolss_notify_status(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 print_status_struct status;
3057 print_queue_length(msg_ctx, snum, &status);
3058 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3061 /*******************************************************************
3062 * fill a notify_info_data with the number of jobs queued
3063 ********************************************************************/
3065 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3066 int snum,
3067 struct spoolss_Notify *data,
3068 print_queue_struct *queue,
3069 struct spoolss_PrinterInfo2 *pinfo2,
3070 TALLOC_CTX *mem_ctx)
3072 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3073 data, print_queue_length(msg_ctx, snum, NULL));
3076 /*******************************************************************
3077 * fill a notify_info_data with the average ppm
3078 ********************************************************************/
3080 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3081 int snum,
3082 struct spoolss_Notify *data,
3083 print_queue_struct *queue,
3084 struct spoolss_PrinterInfo2 *pinfo2,
3085 TALLOC_CTX *mem_ctx)
3087 /* always respond 8 pages per minutes */
3088 /* a little hard ! */
3089 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3092 /*******************************************************************
3093 * fill a notify_info_data with username
3094 ********************************************************************/
3096 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3097 int snum,
3098 struct spoolss_Notify *data,
3099 print_queue_struct *queue,
3100 struct spoolss_PrinterInfo2 *pinfo2,
3101 TALLOC_CTX *mem_ctx)
3103 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3106 /*******************************************************************
3107 * fill a notify_info_data with job status
3108 ********************************************************************/
3110 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3111 int snum,
3112 struct spoolss_Notify *data,
3113 print_queue_struct *queue,
3114 struct spoolss_PrinterInfo2 *pinfo2,
3115 TALLOC_CTX *mem_ctx)
3117 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3120 /*******************************************************************
3121 * fill a notify_info_data with job name
3122 ********************************************************************/
3124 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3125 int snum,
3126 struct spoolss_Notify *data,
3127 print_queue_struct *queue,
3128 struct spoolss_PrinterInfo2 *pinfo2,
3129 TALLOC_CTX *mem_ctx)
3131 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3134 /*******************************************************************
3135 * fill a notify_info_data with job status
3136 ********************************************************************/
3138 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3139 int snum,
3140 struct spoolss_Notify *data,
3141 print_queue_struct *queue,
3142 struct spoolss_PrinterInfo2 *pinfo2,
3143 TALLOC_CTX *mem_ctx)
3146 * Now we're returning job status codes we just return a "" here. JRA.
3149 const char *p = "";
3151 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3152 p = "unknown";
3154 switch (queue->status) {
3155 case LPQ_QUEUED:
3156 p = "Queued";
3157 break;
3158 case LPQ_PAUSED:
3159 p = ""; /* NT provides the paused string */
3160 break;
3161 case LPQ_SPOOLING:
3162 p = "Spooling";
3163 break;
3164 case LPQ_PRINTING:
3165 p = "Printing";
3166 break;
3168 #endif /* NO LONGER NEEDED. */
3170 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3173 /*******************************************************************
3174 * fill a notify_info_data with job time
3175 ********************************************************************/
3177 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3178 int snum,
3179 struct spoolss_Notify *data,
3180 print_queue_struct *queue,
3181 struct spoolss_PrinterInfo2 *pinfo2,
3182 TALLOC_CTX *mem_ctx)
3184 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3187 /*******************************************************************
3188 * fill a notify_info_data with job size
3189 ********************************************************************/
3191 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3192 int snum,
3193 struct spoolss_Notify *data,
3194 print_queue_struct *queue,
3195 struct spoolss_PrinterInfo2 *pinfo2,
3196 TALLOC_CTX *mem_ctx)
3198 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3201 /*******************************************************************
3202 * fill a notify_info_data with page info
3203 ********************************************************************/
3204 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3205 int snum,
3206 struct spoolss_Notify *data,
3207 print_queue_struct *queue,
3208 struct spoolss_PrinterInfo2 *pinfo2,
3209 TALLOC_CTX *mem_ctx)
3211 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3214 /*******************************************************************
3215 * fill a notify_info_data with pages printed info.
3216 ********************************************************************/
3217 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3218 int snum,
3219 struct spoolss_Notify *data,
3220 print_queue_struct *queue,
3221 struct spoolss_PrinterInfo2 *pinfo2,
3222 TALLOC_CTX *mem_ctx)
3224 /* Add code when back-end tracks this */
3225 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3228 /*******************************************************************
3229 Fill a notify_info_data with job position.
3230 ********************************************************************/
3232 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3233 int snum,
3234 struct spoolss_Notify *data,
3235 print_queue_struct *queue,
3236 struct spoolss_PrinterInfo2 *pinfo2,
3237 TALLOC_CTX *mem_ctx)
3239 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3242 /*******************************************************************
3243 Fill a notify_info_data with submitted time.
3244 ********************************************************************/
3246 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3247 int snum,
3248 struct spoolss_Notify *data,
3249 print_queue_struct *queue,
3250 struct spoolss_PrinterInfo2 *pinfo2,
3251 TALLOC_CTX *mem_ctx)
3253 data->data.string.string = NULL;
3254 data->data.string.size = 0;
3256 init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3257 &data->data.string.string,
3258 &data->data.string.size);
3262 struct s_notify_info_data_table
3264 enum spoolss_NotifyType type;
3265 uint16_t field;
3266 const char *name;
3267 enum spoolss_NotifyTable variable_type;
3268 void (*fn) (struct messaging_context *msg_ctx,
3269 int snum, struct spoolss_Notify *data,
3270 print_queue_struct *queue,
3271 struct spoolss_PrinterInfo2 *pinfo2,
3272 TALLOC_CTX *mem_ctx);
3275 /* A table describing the various print notification constants and
3276 whether the notification data is a pointer to a variable sized
3277 buffer, a one value uint32_t or a two value uint32_t. */
3279 static const struct s_notify_info_data_table notify_info_data_table[] =
3281 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3282 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3283 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
3284 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3285 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3286 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
3287 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
3288 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3289 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
3290 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3291 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3292 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3293 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
3294 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
3295 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3296 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
3297 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3298 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3299 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
3300 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
3301 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
3302 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
3303 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
3304 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3305 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
3306 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3307 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINTER_NAME, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3308 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_MACHINE_NAME, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3309 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PORT_NAME, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3310 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_USER_NAME, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3311 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_NOTIFY_NAME, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3312 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DATATYPE, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3313 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINT_PROCESSOR, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3314 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PARAMETERS, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3315 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DRIVER_NAME, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3316 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DEVMODE, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3317 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
3318 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS_STRING, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
3319 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
3320 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DOCUMENT, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
3321 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRIORITY, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3322 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_POSITION, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
3323 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SUBMITTED, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
3324 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_START_TIME, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3325 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_UNTIL_TIME, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3326 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TIME, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
3327 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_PAGES, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
3328 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PAGES_PRINTED, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
3329 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_BYTES, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
3332 /*******************************************************************
3333 Return the variable_type of info_data structure.
3334 ********************************************************************/
3336 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3337 uint16_t field)
3339 int i=0;
3341 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3342 if ( (notify_info_data_table[i].type == type) &&
3343 (notify_info_data_table[i].field == field) ) {
3344 return notify_info_data_table[i].variable_type;
3348 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3350 return (enum spoolss_NotifyTable) 0;
3353 /****************************************************************************
3354 ****************************************************************************/
3356 static bool search_notify(enum spoolss_NotifyType type,
3357 uint16_t field,
3358 int *value)
3360 int i;
3362 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3363 if (notify_info_data_table[i].type == type &&
3364 notify_info_data_table[i].field == field &&
3365 notify_info_data_table[i].fn != NULL) {
3366 *value = i;
3367 return true;
3371 return false;
3374 /****************************************************************************
3375 ****************************************************************************/
3377 static void construct_info_data(struct spoolss_Notify *info_data,
3378 enum spoolss_NotifyType type,
3379 uint16_t field, int id)
3381 info_data->type = type;
3382 info_data->field.field = field;
3383 info_data->variable_type = variable_type_of_notify_info_data(type, field);
3384 info_data->job_id = id;
3387 /*******************************************************************
3389 * fill a notify_info struct with info asked
3391 ********************************************************************/
3393 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3394 struct printer_handle *print_hnd,
3395 struct spoolss_NotifyInfo *info,
3396 struct spoolss_PrinterInfo2 *pinfo2,
3397 int snum,
3398 const struct spoolss_NotifyOptionType *option_type,
3399 uint32_t id,
3400 TALLOC_CTX *mem_ctx)
3402 int field_num,j;
3403 enum spoolss_NotifyType type;
3404 uint16_t field;
3406 struct spoolss_Notify *current_data;
3407 print_queue_struct *queue=NULL;
3409 type = option_type->type;
3411 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3412 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3413 option_type->count, lp_servicename(snum)));
3415 for(field_num=0; field_num < option_type->count; field_num++) {
3416 field = option_type->fields[field_num].field;
3418 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3420 if (!search_notify(type, field, &j) )
3421 continue;
3423 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3424 struct spoolss_Notify,
3425 info->count + 1);
3426 if (info->notifies == NULL) {
3427 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3428 return false;
3431 current_data = &info->notifies[info->count];
3433 construct_info_data(current_data, type, field, id);
3435 DEBUG(10, ("construct_notify_printer_info: "
3436 "calling [%s] snum=%d printername=[%s])\n",
3437 notify_info_data_table[j].name, snum,
3438 pinfo2->printername));
3440 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3441 queue, pinfo2, mem_ctx);
3443 info->count++;
3446 return true;
3449 /*******************************************************************
3451 * fill a notify_info struct with info asked
3453 ********************************************************************/
3455 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3456 print_queue_struct *queue,
3457 struct spoolss_NotifyInfo *info,
3458 struct spoolss_PrinterInfo2 *pinfo2,
3459 int snum,
3460 const struct spoolss_NotifyOptionType *option_type,
3461 uint32_t id,
3462 TALLOC_CTX *mem_ctx)
3464 int field_num,j;
3465 enum spoolss_NotifyType type;
3466 uint16_t field;
3467 struct spoolss_Notify *current_data;
3469 DEBUG(4,("construct_notify_jobs_info\n"));
3471 type = option_type->type;
3473 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3474 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3475 option_type->count));
3477 for(field_num=0; field_num<option_type->count; field_num++) {
3478 field = option_type->fields[field_num].field;
3480 if (!search_notify(type, field, &j) )
3481 continue;
3483 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3484 struct spoolss_Notify,
3485 info->count + 1);
3486 if (info->notifies == NULL) {
3487 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3488 return false;
3491 current_data=&(info->notifies[info->count]);
3493 construct_info_data(current_data, type, field, id);
3494 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3495 queue, pinfo2, mem_ctx);
3496 info->count++;
3499 return true;
3503 * JFM: The enumeration is not that simple, it's even non obvious.
3505 * let's take an example: I want to monitor the PRINTER SERVER for
3506 * the printer's name and the number of jobs currently queued.
3507 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3508 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3510 * I have 3 printers on the back of my server.
3512 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3513 * structures.
3514 * Number Data Id
3515 * 1 printer 1 name 1
3516 * 2 printer 1 cjob 1
3517 * 3 printer 2 name 2
3518 * 4 printer 2 cjob 2
3519 * 5 printer 3 name 3
3520 * 6 printer 3 name 3
3522 * that's the print server case, the printer case is even worse.
3525 /*******************************************************************
3527 * enumerate all printers on the printserver
3528 * fill a notify_info struct with info asked
3530 ********************************************************************/
3532 static WERROR printserver_notify_info(struct pipes_struct *p,
3533 struct policy_handle *hnd,
3534 struct spoolss_NotifyInfo *info,
3535 TALLOC_CTX *mem_ctx)
3537 int snum;
3538 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3539 int n_services=lp_numservices();
3540 int i;
3541 struct spoolss_NotifyOption *option;
3542 struct spoolss_NotifyOptionType option_type;
3543 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3544 WERROR result;
3546 DEBUG(4,("printserver_notify_info\n"));
3548 if (!Printer)
3549 return WERR_BADFID;
3551 option = Printer->notify.option;
3553 info->version = 2;
3554 info->notifies = NULL;
3555 info->count = 0;
3557 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3558 sending a ffpcn() request first */
3560 if ( !option )
3561 return WERR_BADFID;
3563 for (i=0; i<option->count; i++) {
3564 option_type = option->types[i];
3566 if (option_type.type != PRINTER_NOTIFY_TYPE)
3567 continue;
3569 for (snum = 0; snum < n_services; snum++) {
3570 if (!lp_browseable(snum) ||
3571 !lp_snum_ok(snum) ||
3572 !lp_print_ok(snum)) {
3573 continue; /* skip */
3576 /* Maybe we should use the SYSTEM session_info here... */
3577 result = winreg_get_printer(mem_ctx,
3578 get_session_info_system(),
3579 p->msg_ctx,
3580 lp_servicename(snum),
3581 &pinfo2);
3582 if (!W_ERROR_IS_OK(result)) {
3583 DEBUG(4, ("printserver_notify_info: "
3584 "Failed to get printer [%s]\n",
3585 lp_servicename(snum)));
3586 continue;
3590 construct_notify_printer_info(p->msg_ctx,
3591 Printer, info,
3592 pinfo2, snum,
3593 &option_type, snum,
3594 mem_ctx);
3596 TALLOC_FREE(pinfo2);
3600 #if 0
3602 * Debugging information, don't delete.
3605 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3606 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3607 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3609 for (i=0; i<info->count; i++) {
3610 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3611 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3612 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3614 #endif
3616 return WERR_OK;
3619 /*******************************************************************
3621 * fill a notify_info struct with info asked
3623 ********************************************************************/
3625 static WERROR printer_notify_info(struct pipes_struct *p,
3626 struct policy_handle *hnd,
3627 struct spoolss_NotifyInfo *info,
3628 TALLOC_CTX *mem_ctx)
3630 int snum;
3631 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3632 int i;
3633 uint32_t id;
3634 struct spoolss_NotifyOption *option;
3635 struct spoolss_NotifyOptionType option_type;
3636 int count,j;
3637 print_queue_struct *queue=NULL;
3638 print_status_struct status;
3639 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3640 WERROR result;
3642 DEBUG(4,("printer_notify_info\n"));
3644 if (!Printer)
3645 return WERR_BADFID;
3647 option = Printer->notify.option;
3648 id = 0x0;
3650 info->version = 2;
3651 info->notifies = NULL;
3652 info->count = 0;
3654 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3655 sending a ffpcn() request first */
3657 if ( !option )
3658 return WERR_BADFID;
3660 if (!get_printer_snum(p, hnd, &snum, NULL)) {
3661 return WERR_BADFID;
3664 /* Maybe we should use the SYSTEM session_info here... */
3665 result = winreg_get_printer(mem_ctx,
3666 get_session_info_system(),
3667 p->msg_ctx,
3668 lp_servicename(snum), &pinfo2);
3669 if (!W_ERROR_IS_OK(result)) {
3670 return WERR_BADFID;
3673 for (i=0; i<option->count; i++) {
3674 option_type = option->types[i];
3676 switch (option_type.type) {
3677 case PRINTER_NOTIFY_TYPE:
3678 if (construct_notify_printer_info(p->msg_ctx,
3679 Printer, info,
3680 pinfo2, snum,
3681 &option_type, id,
3682 mem_ctx)) {
3683 id--;
3685 break;
3687 case JOB_NOTIFY_TYPE:
3689 count = print_queue_status(p->msg_ctx, snum, &queue,
3690 &status);
3692 for (j=0; j<count; j++) {
3693 construct_notify_jobs_info(p->msg_ctx,
3694 &queue[j], info,
3695 pinfo2, snum,
3696 &option_type,
3697 queue[j].job,
3698 mem_ctx);
3701 SAFE_FREE(queue);
3702 break;
3707 * Debugging information, don't delete.
3710 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3711 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3712 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3714 for (i=0; i<info->count; i++) {
3715 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3716 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3717 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3721 talloc_free(pinfo2);
3722 return WERR_OK;
3725 /****************************************************************
3726 _spoolss_RouterRefreshPrinterChangeNotify
3727 ****************************************************************/
3729 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3730 struct spoolss_RouterRefreshPrinterChangeNotify *r)
3732 struct spoolss_NotifyInfo *info;
3734 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3735 WERROR result = WERR_BADFID;
3737 /* we always have a spoolss_NotifyInfo struct */
3738 info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3739 if (!info) {
3740 result = WERR_NOMEM;
3741 goto done;
3744 *r->out.info = info;
3746 if (!Printer) {
3747 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3748 "Invalid handle (%s:%u:%u).\n",
3749 OUR_HANDLE(r->in.handle)));
3750 goto done;
3753 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3756 * We are now using the change value, and
3757 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3758 * I don't have a global notification system, I'm sending back all the
3759 * information even when _NOTHING_ has changed.
3762 /* We need to keep track of the change value to send back in
3763 RRPCN replies otherwise our updates are ignored. */
3765 Printer->notify.fnpcn = true;
3767 if (Printer->notify.cli_chan != NULL &&
3768 Printer->notify.cli_chan->active_connections > 0) {
3769 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3770 "Saving change value in request [%x]\n",
3771 r->in.change_low));
3772 Printer->notify.change = r->in.change_low;
3775 /* just ignore the spoolss_NotifyOption */
3777 switch (Printer->printer_type) {
3778 case SPLHND_SERVER:
3779 result = printserver_notify_info(p, r->in.handle,
3780 info, p->mem_ctx);
3781 break;
3783 case SPLHND_PRINTER:
3784 result = printer_notify_info(p, r->in.handle,
3785 info, p->mem_ctx);
3786 break;
3789 Printer->notify.fnpcn = false;
3791 done:
3792 return result;
3795 /********************************************************************
3796 ********************************************************************/
3798 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3799 const char *servername,
3800 const char *printername,
3801 const char **printername_p)
3803 /* FIXME: add lp_force_printername() */
3805 if (servername == NULL) {
3806 *printername_p = talloc_strdup(mem_ctx, printername);
3807 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3808 return WERR_OK;
3811 if (servername[0] == '\\' && servername[1] == '\\') {
3812 servername += 2;
3815 *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3816 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3818 return WERR_OK;
3821 /********************************************************************
3822 ********************************************************************/
3824 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3825 const char *printername)
3827 if (dm == NULL) {
3828 return;
3831 dm->devicename = talloc_strndup(dm, printername,
3832 MIN(strlen(printername), 31));
3835 /********************************************************************
3836 * construct_printer_info_0
3837 * fill a printer_info_0 struct
3838 ********************************************************************/
3840 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3841 const struct auth_serversupplied_info *session_info,
3842 struct messaging_context *msg_ctx,
3843 struct spoolss_PrinterInfo2 *info2,
3844 const char *servername,
3845 struct spoolss_PrinterInfo0 *r,
3846 int snum)
3848 int count;
3849 struct printer_session_counter *session_counter;
3850 struct timeval setuptime;
3851 print_status_struct status;
3852 WERROR result;
3854 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3855 if (!W_ERROR_IS_OK(result)) {
3856 return result;
3859 if (servername) {
3860 r->servername = talloc_strdup(mem_ctx, servername);
3861 W_ERROR_HAVE_NO_MEMORY(r->servername);
3862 } else {
3863 r->servername = NULL;
3866 count = print_queue_length(msg_ctx, snum, &status);
3868 /* check if we already have a counter for this printer */
3869 for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3870 if (session_counter->snum == snum)
3871 break;
3874 /* it's the first time, add it to the list */
3875 if (session_counter == NULL) {
3876 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3877 W_ERROR_HAVE_NO_MEMORY(session_counter);
3878 session_counter->snum = snum;
3879 session_counter->counter = 0;
3880 DLIST_ADD(counter_list, session_counter);
3883 /* increment it */
3884 session_counter->counter++;
3886 r->cjobs = count;
3887 r->total_jobs = 0;
3888 r->total_bytes = 0;
3890 get_startup_time(&setuptime);
3891 init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3893 /* JFM:
3894 * the global_counter should be stored in a TDB as it's common to all the clients
3895 * and should be zeroed on samba startup
3897 r->global_counter = session_counter->counter;
3898 r->total_pages = 0;
3899 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3900 SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3901 SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3902 r->free_build = SPOOLSS_RELEASE_BUILD;
3903 r->spooling = 0;
3904 r->max_spooling = 0;
3905 r->session_counter = session_counter->counter;
3906 r->num_error_out_of_paper = 0x0;
3907 r->num_error_not_ready = 0x0; /* number of print failure */
3908 r->job_error = 0x0;
3909 r->number_of_processors = 0x1;
3910 r->processor_type = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3911 r->high_part_total_bytes = 0x0;
3913 /* ChangeID in milliseconds*/
3914 winreg_printer_get_changeid(mem_ctx, session_info, msg_ctx,
3915 info2->sharename, &r->change_id);
3917 r->last_error = WERR_OK;
3918 r->status = nt_printq_status(status.status);
3919 r->enumerate_network_printers = 0x0;
3920 r->c_setprinter = 0x0;
3921 r->processor_architecture = PROCESSOR_ARCHITECTURE_INTEL;
3922 r->processor_level = 0x6; /* 6 ???*/
3923 r->ref_ic = 0;
3924 r->reserved2 = 0;
3925 r->reserved3 = 0;
3927 return WERR_OK;
3931 /********************************************************************
3932 * construct_printer_info1
3933 * fill a spoolss_PrinterInfo1 struct
3934 ********************************************************************/
3936 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3937 const struct spoolss_PrinterInfo2 *info2,
3938 uint32_t flags,
3939 const char *servername,
3940 struct spoolss_PrinterInfo1 *r,
3941 int snum)
3943 WERROR result;
3945 r->flags = flags;
3947 if (info2->comment == NULL || info2->comment[0] == '\0') {
3948 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
3949 } else {
3950 r->comment = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3952 W_ERROR_HAVE_NO_MEMORY(r->comment);
3954 result = create_printername(mem_ctx, servername, info2->printername, &r->name);
3955 if (!W_ERROR_IS_OK(result)) {
3956 return result;
3959 r->description = talloc_asprintf(mem_ctx, "%s,%s,%s",
3960 r->name,
3961 info2->drivername,
3962 r->comment);
3963 W_ERROR_HAVE_NO_MEMORY(r->description);
3965 return WERR_OK;
3968 /********************************************************************
3969 * construct_printer_info2
3970 * fill a spoolss_PrinterInfo2 struct
3971 ********************************************************************/
3973 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3974 struct messaging_context *msg_ctx,
3975 const struct spoolss_PrinterInfo2 *info2,
3976 const char *servername,
3977 struct spoolss_PrinterInfo2 *r,
3978 int snum)
3980 int count;
3981 print_status_struct status;
3982 WERROR result;
3984 count = print_queue_length(msg_ctx, snum, &status);
3986 if (servername) {
3987 r->servername = talloc_strdup(mem_ctx, servername);
3988 W_ERROR_HAVE_NO_MEMORY(r->servername);
3989 } else {
3990 r->servername = NULL;
3993 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3994 if (!W_ERROR_IS_OK(result)) {
3995 return result;
3998 r->sharename = talloc_strdup(mem_ctx, lp_servicename(snum));
3999 W_ERROR_HAVE_NO_MEMORY(r->sharename);
4000 r->portname = talloc_strdup(mem_ctx, info2->portname);
4001 W_ERROR_HAVE_NO_MEMORY(r->portname);
4002 r->drivername = talloc_strdup(mem_ctx, info2->drivername);
4003 W_ERROR_HAVE_NO_MEMORY(r->drivername);
4005 if (info2->comment[0] == '\0') {
4006 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
4007 } else {
4008 r->comment = talloc_strdup(mem_ctx, info2->comment);
4010 W_ERROR_HAVE_NO_MEMORY(r->comment);
4012 r->location = talloc_strdup(mem_ctx, info2->location);
4013 W_ERROR_HAVE_NO_MEMORY(r->location);
4014 r->sepfile = talloc_strdup(mem_ctx, info2->sepfile);
4015 W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4016 r->printprocessor = talloc_strdup(mem_ctx, info2->printprocessor);
4017 W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4018 r->datatype = talloc_strdup(mem_ctx, info2->datatype);
4019 W_ERROR_HAVE_NO_MEMORY(r->datatype);
4020 r->parameters = talloc_strdup(mem_ctx, info2->parameters);
4021 W_ERROR_HAVE_NO_MEMORY(r->parameters);
4023 r->attributes = info2->attributes;
4025 r->priority = info2->priority;
4026 r->defaultpriority = info2->defaultpriority;
4027 r->starttime = info2->starttime;
4028 r->untiltime = info2->untiltime;
4029 r->status = nt_printq_status(status.status);
4030 r->cjobs = count;
4031 r->averageppm = info2->averageppm;
4033 copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4034 if (!r->devmode) {
4035 DEBUG(8,("Returning NULL Devicemode!\n"));
4038 compose_devicemode_devicename(r->devmode, r->printername);
4040 r->secdesc = NULL;
4042 if (info2->secdesc != NULL) {
4043 /* don't use talloc_steal() here unless you do a deep steal of all
4044 the SEC_DESC members */
4046 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4049 return WERR_OK;
4052 /********************************************************************
4053 * construct_printer_info3
4054 * fill a spoolss_PrinterInfo3 struct
4055 ********************************************************************/
4057 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4058 const struct spoolss_PrinterInfo2 *info2,
4059 const char *servername,
4060 struct spoolss_PrinterInfo3 *r,
4061 int snum)
4063 /* These are the components of the SD we are returning. */
4065 if (info2->secdesc != NULL) {
4066 /* don't use talloc_steal() here unless you do a deep steal of all
4067 the SEC_DESC members */
4069 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4070 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
4073 return WERR_OK;
4076 /********************************************************************
4077 * construct_printer_info4
4078 * fill a spoolss_PrinterInfo4 struct
4079 ********************************************************************/
4081 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4082 const struct spoolss_PrinterInfo2 *info2,
4083 const char *servername,
4084 struct spoolss_PrinterInfo4 *r,
4085 int snum)
4087 WERROR result;
4089 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4090 if (!W_ERROR_IS_OK(result)) {
4091 return result;
4094 if (servername) {
4095 r->servername = talloc_strdup(mem_ctx, servername);
4096 W_ERROR_HAVE_NO_MEMORY(r->servername);
4097 } else {
4098 r->servername = NULL;
4101 r->attributes = info2->attributes;
4103 return WERR_OK;
4106 /********************************************************************
4107 * construct_printer_info5
4108 * fill a spoolss_PrinterInfo5 struct
4109 ********************************************************************/
4111 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4112 const struct spoolss_PrinterInfo2 *info2,
4113 const char *servername,
4114 struct spoolss_PrinterInfo5 *r,
4115 int snum)
4117 WERROR result;
4119 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4120 if (!W_ERROR_IS_OK(result)) {
4121 return result;
4124 r->portname = talloc_strdup(mem_ctx, info2->portname);
4125 W_ERROR_HAVE_NO_MEMORY(r->portname);
4127 r->attributes = info2->attributes;
4129 /* these two are not used by NT+ according to MSDN */
4130 r->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4131 r->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4133 return WERR_OK;
4136 /********************************************************************
4137 * construct_printer_info_6
4138 * fill a spoolss_PrinterInfo6 struct
4139 ********************************************************************/
4141 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4142 struct messaging_context *msg_ctx,
4143 const struct spoolss_PrinterInfo2 *info2,
4144 const char *servername,
4145 struct spoolss_PrinterInfo6 *r,
4146 int snum)
4148 int count;
4149 print_status_struct status;
4151 count = print_queue_length(msg_ctx, snum, &status);
4153 r->status = nt_printq_status(status.status);
4155 return WERR_OK;
4158 /********************************************************************
4159 * construct_printer_info7
4160 * fill a spoolss_PrinterInfo7 struct
4161 ********************************************************************/
4163 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4164 struct messaging_context *msg_ctx,
4165 const char *servername,
4166 struct spoolss_PrinterInfo7 *r,
4167 int snum)
4169 struct auth_serversupplied_info *session_info;
4170 struct GUID guid;
4171 NTSTATUS status;
4173 status = make_session_info_system(mem_ctx, &session_info);
4174 if (!NT_STATUS_IS_OK(status)) {
4175 DEBUG(0, ("construct_printer_info7: "
4176 "Could not create system session_info\n"));
4177 return WERR_NOMEM;
4180 if (is_printer_published(mem_ctx, session_info, msg_ctx,
4181 servername,
4182 lp_servicename(snum), &guid, NULL)) {
4183 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4184 r->action = DSPRINT_PUBLISH;
4185 } else {
4186 r->guid = talloc_strdup(mem_ctx, "");
4187 r->action = DSPRINT_UNPUBLISH;
4189 W_ERROR_HAVE_NO_MEMORY(r->guid);
4191 TALLOC_FREE(session_info);
4192 return WERR_OK;
4195 /********************************************************************
4196 * construct_printer_info8
4197 * fill a spoolss_PrinterInfo8 struct
4198 ********************************************************************/
4200 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4201 const struct spoolss_PrinterInfo2 *info2,
4202 const char *servername,
4203 struct spoolss_DeviceModeInfo *r,
4204 int snum)
4206 WERROR result;
4207 const char *printername;
4209 result = create_printername(mem_ctx, servername, info2->printername, &printername);
4210 if (!W_ERROR_IS_OK(result)) {
4211 return result;
4214 copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4215 if (!r->devmode) {
4216 DEBUG(8,("Returning NULL Devicemode!\n"));
4219 compose_devicemode_devicename(r->devmode, printername);
4221 return WERR_OK;
4225 /********************************************************************
4226 ********************************************************************/
4228 static bool snum_is_shared_printer(int snum)
4230 return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4233 /********************************************************************
4234 Spoolss_enumprinters.
4235 ********************************************************************/
4237 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4238 const struct auth_serversupplied_info *session_info,
4239 struct messaging_context *msg_ctx,
4240 const char *servername,
4241 uint32_t level,
4242 uint32_t flags,
4243 union spoolss_PrinterInfo **info_p,
4244 uint32_t *count_p)
4246 int snum;
4247 int n_services = lp_numservices();
4248 union spoolss_PrinterInfo *info = NULL;
4249 uint32_t count = 0;
4250 WERROR result = WERR_OK;
4252 *count_p = 0;
4253 *info_p = NULL;
4255 for (snum = 0; snum < n_services; snum++) {
4257 const char *printer;
4258 struct spoolss_PrinterInfo2 *info2;
4260 if (!snum_is_shared_printer(snum)) {
4261 continue;
4264 printer = lp_const_servicename(snum);
4266 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4267 printer, snum));
4269 result = winreg_create_printer(mem_ctx,
4270 session_info,
4271 msg_ctx,
4272 printer);
4273 if (!W_ERROR_IS_OK(result)) {
4274 goto out;
4277 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4278 union spoolss_PrinterInfo,
4279 count + 1);
4280 if (!info) {
4281 result = WERR_NOMEM;
4282 goto out;
4285 result = winreg_get_printer(mem_ctx, session_info, msg_ctx,
4286 printer, &info2);
4287 if (!W_ERROR_IS_OK(result)) {
4288 goto out;
4291 switch (level) {
4292 case 0:
4293 result = construct_printer_info0(info, session_info,
4294 msg_ctx, info2,
4295 servername,
4296 &info[count].info0, snum);
4297 break;
4298 case 1:
4299 result = construct_printer_info1(info, info2, flags,
4300 servername,
4301 &info[count].info1, snum);
4302 break;
4303 case 2:
4304 result = construct_printer_info2(info, msg_ctx, info2,
4305 servername,
4306 &info[count].info2, snum);
4307 break;
4308 case 4:
4309 result = construct_printer_info4(info, info2,
4310 servername,
4311 &info[count].info4, snum);
4312 break;
4313 case 5:
4314 result = construct_printer_info5(info, info2,
4315 servername,
4316 &info[count].info5, snum);
4317 break;
4319 default:
4320 result = WERR_UNKNOWN_LEVEL;
4321 goto out;
4324 if (!W_ERROR_IS_OK(result)) {
4325 goto out;
4328 count++;
4331 *count_p = count;
4332 *info_p = info;
4334 out:
4335 if (!W_ERROR_IS_OK(result)) {
4336 TALLOC_FREE(info);
4337 return result;
4340 *info_p = info;
4342 return WERR_OK;
4345 /********************************************************************
4346 * handle enumeration of printers at level 0
4347 ********************************************************************/
4349 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4350 const struct auth_serversupplied_info *session_info,
4351 struct messaging_context *msg_ctx,
4352 uint32_t flags,
4353 const char *servername,
4354 union spoolss_PrinterInfo **info,
4355 uint32_t *count)
4357 DEBUG(4,("enum_all_printers_info_0\n"));
4359 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4360 servername, 0, flags, info, count);
4364 /********************************************************************
4365 ********************************************************************/
4367 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4368 const struct auth_serversupplied_info *session_info,
4369 struct messaging_context *msg_ctx,
4370 const char *servername,
4371 uint32_t flags,
4372 union spoolss_PrinterInfo **info,
4373 uint32_t *count)
4375 DEBUG(4,("enum_all_printers_info_1\n"));
4377 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4378 servername, 1, flags, info, count);
4381 /********************************************************************
4382 enum_all_printers_info_1_local.
4383 *********************************************************************/
4385 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4386 const struct auth_serversupplied_info *session_info,
4387 struct messaging_context *msg_ctx,
4388 const char *servername,
4389 union spoolss_PrinterInfo **info,
4390 uint32_t *count)
4392 DEBUG(4,("enum_all_printers_info_1_local\n"));
4394 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4395 servername, PRINTER_ENUM_ICON8, info, count);
4398 /********************************************************************
4399 enum_all_printers_info_1_name.
4400 *********************************************************************/
4402 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4403 const struct auth_serversupplied_info *session_info,
4404 struct messaging_context *msg_ctx,
4405 const char *servername,
4406 union spoolss_PrinterInfo **info,
4407 uint32_t *count)
4409 const char *s = servername;
4411 DEBUG(4,("enum_all_printers_info_1_name\n"));
4413 if ((servername[0] == '\\') && (servername[1] == '\\')) {
4414 s = servername + 2;
4417 if (!is_myname_or_ipaddr(s)) {
4418 return WERR_INVALID_NAME;
4421 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4422 servername, PRINTER_ENUM_ICON8, info, count);
4425 /********************************************************************
4426 enum_all_printers_info_1_network.
4427 *********************************************************************/
4429 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4430 const struct auth_serversupplied_info *session_info,
4431 struct messaging_context *msg_ctx,
4432 const char *servername,
4433 union spoolss_PrinterInfo **info,
4434 uint32_t *count)
4436 const char *s = servername;
4438 DEBUG(4,("enum_all_printers_info_1_network\n"));
4440 /* If we respond to a enum_printers level 1 on our name with flags
4441 set to PRINTER_ENUM_REMOTE with a list of printers then these
4442 printers incorrectly appear in the APW browse list.
4443 Specifically the printers for the server appear at the workgroup
4444 level where all the other servers in the domain are
4445 listed. Windows responds to this call with a
4446 WERR_CAN_NOT_COMPLETE so we should do the same. */
4448 if (servername[0] == '\\' && servername[1] == '\\') {
4449 s = servername + 2;
4452 if (is_myname_or_ipaddr(s)) {
4453 return WERR_CAN_NOT_COMPLETE;
4456 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4457 servername, PRINTER_ENUM_NAME, info, count);
4460 /********************************************************************
4461 * api_spoolss_enumprinters
4463 * called from api_spoolss_enumprinters (see this to understand)
4464 ********************************************************************/
4466 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4467 const struct auth_serversupplied_info *session_info,
4468 struct messaging_context *msg_ctx,
4469 const char *servername,
4470 union spoolss_PrinterInfo **info,
4471 uint32_t *count)
4473 DEBUG(4,("enum_all_printers_info_2\n"));
4475 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4476 servername, 2, 0, info, count);
4479 /********************************************************************
4480 * handle enumeration of printers at level 1
4481 ********************************************************************/
4483 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4484 const struct auth_serversupplied_info *session_info,
4485 struct messaging_context *msg_ctx,
4486 uint32_t flags,
4487 const char *servername,
4488 union spoolss_PrinterInfo **info,
4489 uint32_t *count)
4491 /* Not all the flags are equals */
4493 if (flags & PRINTER_ENUM_LOCAL) {
4494 return enum_all_printers_info_1_local(mem_ctx, session_info,
4495 msg_ctx, servername, info, count);
4498 if (flags & PRINTER_ENUM_NAME) {
4499 return enum_all_printers_info_1_name(mem_ctx, session_info,
4500 msg_ctx, servername, info,
4501 count);
4504 if (flags & PRINTER_ENUM_NETWORK) {
4505 return enum_all_printers_info_1_network(mem_ctx, session_info,
4506 msg_ctx, servername, info,
4507 count);
4510 return WERR_OK; /* NT4sp5 does that */
4513 /********************************************************************
4514 * handle enumeration of printers at level 2
4515 ********************************************************************/
4517 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4518 const struct auth_serversupplied_info *session_info,
4519 struct messaging_context *msg_ctx,
4520 uint32_t flags,
4521 const char *servername,
4522 union spoolss_PrinterInfo **info,
4523 uint32_t *count)
4525 if (flags & PRINTER_ENUM_LOCAL) {
4527 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4528 servername,
4529 info, count);
4532 if (flags & PRINTER_ENUM_NAME) {
4533 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4534 return WERR_INVALID_NAME;
4537 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4538 servername,
4539 info, count);
4542 if (flags & PRINTER_ENUM_REMOTE) {
4543 return WERR_UNKNOWN_LEVEL;
4546 return WERR_OK;
4549 /********************************************************************
4550 * handle enumeration of printers at level 4
4551 ********************************************************************/
4553 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4554 const struct auth_serversupplied_info *session_info,
4555 struct messaging_context *msg_ctx,
4556 uint32_t flags,
4557 const char *servername,
4558 union spoolss_PrinterInfo **info,
4559 uint32_t *count)
4561 DEBUG(4,("enum_all_printers_info_4\n"));
4563 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4564 servername, 4, flags, info, count);
4568 /********************************************************************
4569 * handle enumeration of printers at level 5
4570 ********************************************************************/
4572 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4573 const struct auth_serversupplied_info *session_info,
4574 struct messaging_context *msg_ctx,
4575 uint32_t flags,
4576 const char *servername,
4577 union spoolss_PrinterInfo **info,
4578 uint32_t *count)
4580 DEBUG(4,("enum_all_printers_info_5\n"));
4582 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4583 servername, 5, flags, info, count);
4586 /****************************************************************
4587 _spoolss_EnumPrinters
4588 ****************************************************************/
4590 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4591 struct spoolss_EnumPrinters *r)
4593 const struct auth_serversupplied_info *session_info = get_session_info_system();
4594 WERROR result;
4596 /* that's an [in out] buffer */
4598 if (!r->in.buffer && (r->in.offered != 0)) {
4599 return WERR_INVALID_PARAM;
4602 DEBUG(4,("_spoolss_EnumPrinters\n"));
4604 *r->out.needed = 0;
4605 *r->out.count = 0;
4606 *r->out.info = NULL;
4609 * Level 1:
4610 * flags==PRINTER_ENUM_NAME
4611 * if name=="" then enumerates all printers
4612 * if name!="" then enumerate the printer
4613 * flags==PRINTER_ENUM_REMOTE
4614 * name is NULL, enumerate printers
4615 * Level 2: name!="" enumerates printers, name can't be NULL
4616 * Level 3: doesn't exist
4617 * Level 4: does a local registry lookup
4618 * Level 5: same as Level 2
4621 if (r->in.server && r->in.server[0] == '\0') {
4622 r->in.server = NULL;
4625 switch (r->in.level) {
4626 case 0:
4627 result = enumprinters_level0(p->mem_ctx, session_info,
4628 p->msg_ctx, r->in.flags,
4629 r->in.server,
4630 r->out.info, r->out.count);
4631 break;
4632 case 1:
4633 result = enumprinters_level1(p->mem_ctx, session_info,
4634 p->msg_ctx, r->in.flags,
4635 r->in.server,
4636 r->out.info, r->out.count);
4637 break;
4638 case 2:
4639 result = enumprinters_level2(p->mem_ctx, session_info,
4640 p->msg_ctx, r->in.flags,
4641 r->in.server,
4642 r->out.info, r->out.count);
4643 break;
4644 case 4:
4645 result = enumprinters_level4(p->mem_ctx, session_info,
4646 p->msg_ctx, r->in.flags,
4647 r->in.server,
4648 r->out.info, r->out.count);
4649 break;
4650 case 5:
4651 result = enumprinters_level5(p->mem_ctx, session_info,
4652 p->msg_ctx, r->in.flags,
4653 r->in.server,
4654 r->out.info, r->out.count);
4655 break;
4656 default:
4657 return WERR_UNKNOWN_LEVEL;
4660 if (!W_ERROR_IS_OK(result)) {
4661 return result;
4664 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4665 spoolss_EnumPrinters,
4666 *r->out.info, r->in.level,
4667 *r->out.count);
4668 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4669 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4671 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4674 /****************************************************************
4675 _spoolss_GetPrinter
4676 ****************************************************************/
4678 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4679 struct spoolss_GetPrinter *r)
4681 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4682 struct spoolss_PrinterInfo2 *info2 = NULL;
4683 WERROR result = WERR_OK;
4684 int snum;
4686 /* that's an [in out] buffer */
4688 if (!r->in.buffer && (r->in.offered != 0)) {
4689 return WERR_INVALID_PARAM;
4692 *r->out.needed = 0;
4694 if (Printer == NULL) {
4695 return WERR_BADFID;
4698 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4699 return WERR_BADFID;
4702 result = winreg_get_printer(p->mem_ctx,
4703 get_session_info_system(),
4704 p->msg_ctx,
4705 lp_const_servicename(snum),
4706 &info2);
4707 if (!W_ERROR_IS_OK(result)) {
4708 goto out;
4711 switch (r->in.level) {
4712 case 0:
4713 result = construct_printer_info0(p->mem_ctx,
4714 get_session_info_system(),
4715 p->msg_ctx,
4716 info2,
4717 Printer->servername,
4718 &r->out.info->info0,
4719 snum);
4720 break;
4721 case 1:
4722 result = construct_printer_info1(p->mem_ctx, info2,
4723 PRINTER_ENUM_ICON8,
4724 Printer->servername,
4725 &r->out.info->info1, snum);
4726 break;
4727 case 2:
4728 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4729 Printer->servername,
4730 &r->out.info->info2, snum);
4731 break;
4732 case 3:
4733 result = construct_printer_info3(p->mem_ctx, info2,
4734 Printer->servername,
4735 &r->out.info->info3, snum);
4736 break;
4737 case 4:
4738 result = construct_printer_info4(p->mem_ctx, info2,
4739 Printer->servername,
4740 &r->out.info->info4, snum);
4741 break;
4742 case 5:
4743 result = construct_printer_info5(p->mem_ctx, info2,
4744 Printer->servername,
4745 &r->out.info->info5, snum);
4746 break;
4747 case 6:
4748 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4749 Printer->servername,
4750 &r->out.info->info6, snum);
4751 break;
4752 case 7:
4753 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4754 Printer->servername,
4755 &r->out.info->info7, snum);
4756 break;
4757 case 8:
4758 result = construct_printer_info8(p->mem_ctx, info2,
4759 Printer->servername,
4760 &r->out.info->info8, snum);
4761 break;
4762 default:
4763 result = WERR_UNKNOWN_LEVEL;
4764 break;
4767 out:
4768 if (!W_ERROR_IS_OK(result)) {
4769 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4770 r->in.level, win_errstr(result)));
4771 TALLOC_FREE(r->out.info);
4772 return result;
4775 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4776 r->out.info, r->in.level);
4777 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4779 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4782 /********************************************************************
4783 ********************************************************************/
4785 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4786 do { \
4787 if (in && strlen(in)) { \
4788 out = talloc_strdup(mem_ctx, in); \
4789 } else { \
4790 out = talloc_strdup(mem_ctx, ""); \
4792 W_ERROR_HAVE_NO_MEMORY(out); \
4793 } while (0);
4795 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4796 do { \
4797 if (in && strlen(in)) { \
4798 out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4799 } else { \
4800 out = talloc_strdup(mem_ctx, ""); \
4802 W_ERROR_HAVE_NO_MEMORY(out); \
4803 } while (0);
4805 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4806 const char **string_array,
4807 const char ***presult,
4808 const char *cservername,
4809 const char *arch,
4810 int version)
4812 int i, num_strings = 0;
4813 const char **array = NULL;
4815 if (string_array == NULL) {
4816 return WERR_INVALID_PARAMETER;
4819 for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4820 const char *str = NULL;
4822 if (cservername == NULL || arch == NULL) {
4823 FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4824 } else {
4825 FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4828 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4829 TALLOC_FREE(array);
4830 return WERR_NOMEM;
4834 if (i > 0) {
4835 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4836 &array, &num_strings);
4839 if (presult) {
4840 *presult = array;
4843 return WERR_OK;
4846 /********************************************************************
4847 * fill a spoolss_DriverInfo1 struct
4848 ********************************************************************/
4850 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4851 struct spoolss_DriverInfo1 *r,
4852 const struct spoolss_DriverInfo8 *driver,
4853 const char *servername)
4855 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4856 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4858 return WERR_OK;
4861 /********************************************************************
4862 * fill a spoolss_DriverInfo2 struct
4863 ********************************************************************/
4865 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4866 struct spoolss_DriverInfo2 *r,
4867 const struct spoolss_DriverInfo8 *driver,
4868 const char *servername)
4871 const char *cservername = canon_servername(servername);
4873 r->version = driver->version;
4875 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4876 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4877 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4878 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4880 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4881 driver->architecture,
4882 driver->version,
4883 driver->driver_path,
4884 r->driver_path);
4886 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4887 driver->architecture,
4888 driver->version,
4889 driver->data_file,
4890 r->data_file);
4892 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4893 driver->architecture,
4894 driver->version,
4895 driver->config_file,
4896 r->config_file);
4898 return WERR_OK;
4901 /********************************************************************
4902 * fill a spoolss_DriverInfo3 struct
4903 ********************************************************************/
4905 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4906 struct spoolss_DriverInfo3 *r,
4907 const struct spoolss_DriverInfo8 *driver,
4908 const char *servername)
4910 const char *cservername = canon_servername(servername);
4912 r->version = driver->version;
4914 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4915 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4916 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4917 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4919 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4920 driver->architecture,
4921 driver->version,
4922 driver->driver_path,
4923 r->driver_path);
4925 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4926 driver->architecture,
4927 driver->version,
4928 driver->data_file,
4929 r->data_file);
4931 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4932 driver->architecture,
4933 driver->version,
4934 driver->config_file,
4935 r->config_file);
4937 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4938 driver->architecture,
4939 driver->version,
4940 driver->help_file,
4941 r->help_file);
4943 FILL_DRIVER_STRING(mem_ctx,
4944 driver->monitor_name,
4945 r->monitor_name);
4947 FILL_DRIVER_STRING(mem_ctx,
4948 driver->default_datatype,
4949 r->default_datatype);
4951 return string_array_from_driver_info(mem_ctx,
4952 driver->dependent_files,
4953 &r->dependent_files,
4954 cservername,
4955 driver->architecture,
4956 driver->version);
4959 /********************************************************************
4960 * fill a spoolss_DriverInfo4 struct
4961 ********************************************************************/
4963 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4964 struct spoolss_DriverInfo4 *r,
4965 const struct spoolss_DriverInfo8 *driver,
4966 const char *servername)
4968 const char *cservername = canon_servername(servername);
4969 WERROR result;
4971 r->version = driver->version;
4973 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4974 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4975 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4976 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4978 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4979 driver->architecture,
4980 driver->version,
4981 driver->driver_path,
4982 r->driver_path);
4984 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4985 driver->architecture,
4986 driver->version,
4987 driver->data_file,
4988 r->data_file);
4990 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4991 driver->architecture,
4992 driver->version,
4993 driver->config_file,
4994 r->config_file);
4996 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4997 driver->architecture,
4998 driver->version,
4999 driver->help_file,
5000 r->help_file);
5002 result = string_array_from_driver_info(mem_ctx,
5003 driver->dependent_files,
5004 &r->dependent_files,
5005 cservername,
5006 driver->architecture,
5007 driver->version);
5008 if (!W_ERROR_IS_OK(result)) {
5009 return result;
5012 FILL_DRIVER_STRING(mem_ctx,
5013 driver->monitor_name,
5014 r->monitor_name);
5016 FILL_DRIVER_STRING(mem_ctx,
5017 driver->default_datatype,
5018 r->default_datatype);
5021 result = string_array_from_driver_info(mem_ctx,
5022 driver->previous_names,
5023 &r->previous_names,
5024 NULL, NULL, 0);
5026 return result;
5029 /********************************************************************
5030 * fill a spoolss_DriverInfo5 struct
5031 ********************************************************************/
5033 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5034 struct spoolss_DriverInfo5 *r,
5035 const struct spoolss_DriverInfo8 *driver,
5036 const char *servername)
5038 const char *cservername = canon_servername(servername);
5040 r->version = driver->version;
5042 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5043 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5044 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5045 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5047 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5048 driver->architecture,
5049 driver->version,
5050 driver->driver_path,
5051 r->driver_path);
5053 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5054 driver->architecture,
5055 driver->version,
5056 driver->data_file,
5057 r->data_file);
5059 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5060 driver->architecture,
5061 driver->version,
5062 driver->config_file,
5063 r->config_file);
5065 r->driver_attributes = 0;
5066 r->config_version = 0;
5067 r->driver_version = 0;
5069 return WERR_OK;
5071 /********************************************************************
5072 * fill a spoolss_DriverInfo6 struct
5073 ********************************************************************/
5075 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5076 struct spoolss_DriverInfo6 *r,
5077 const struct spoolss_DriverInfo8 *driver,
5078 const char *servername)
5080 const char *cservername = canon_servername(servername);
5081 WERROR result;
5083 r->version = driver->version;
5085 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5086 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5087 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5088 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5090 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5091 driver->architecture,
5092 driver->version,
5093 driver->driver_path,
5094 r->driver_path);
5096 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5097 driver->architecture,
5098 driver->version,
5099 driver->data_file,
5100 r->data_file);
5102 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5103 driver->architecture,
5104 driver->version,
5105 driver->config_file,
5106 r->config_file);
5108 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5109 driver->architecture,
5110 driver->version,
5111 driver->help_file,
5112 r->help_file);
5114 FILL_DRIVER_STRING(mem_ctx,
5115 driver->monitor_name,
5116 r->monitor_name);
5118 FILL_DRIVER_STRING(mem_ctx,
5119 driver->default_datatype,
5120 r->default_datatype);
5122 result = string_array_from_driver_info(mem_ctx,
5123 driver->dependent_files,
5124 &r->dependent_files,
5125 cservername,
5126 driver->architecture,
5127 driver->version);
5128 if (!W_ERROR_IS_OK(result)) {
5129 return result;
5132 result = string_array_from_driver_info(mem_ctx,
5133 driver->previous_names,
5134 &r->previous_names,
5135 NULL, NULL, 0);
5136 if (!W_ERROR_IS_OK(result)) {
5137 return result;
5140 r->driver_date = driver->driver_date;
5141 r->driver_version = driver->driver_version;
5143 FILL_DRIVER_STRING(mem_ctx,
5144 driver->manufacturer_name,
5145 r->manufacturer_name);
5146 FILL_DRIVER_STRING(mem_ctx,
5147 driver->manufacturer_url,
5148 r->manufacturer_url);
5149 FILL_DRIVER_STRING(mem_ctx,
5150 driver->hardware_id,
5151 r->hardware_id);
5152 FILL_DRIVER_STRING(mem_ctx,
5153 driver->provider,
5154 r->provider);
5156 return WERR_OK;
5159 /********************************************************************
5160 * fill a spoolss_DriverInfo8 struct
5161 ********************************************************************/
5163 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5164 struct spoolss_DriverInfo8 *r,
5165 const struct spoolss_DriverInfo8 *driver,
5166 const char *servername)
5168 const char *cservername = canon_servername(servername);
5169 WERROR result;
5171 r->version = driver->version;
5173 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5174 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5175 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5176 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5178 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5179 driver->architecture,
5180 driver->version,
5181 driver->driver_path,
5182 r->driver_path);
5184 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5185 driver->architecture,
5186 driver->version,
5187 driver->data_file,
5188 r->data_file);
5190 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5191 driver->architecture,
5192 driver->version,
5193 driver->config_file,
5194 r->config_file);
5196 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5197 driver->architecture,
5198 driver->version,
5199 driver->help_file,
5200 r->help_file);
5202 FILL_DRIVER_STRING(mem_ctx,
5203 driver->monitor_name,
5204 r->monitor_name);
5206 FILL_DRIVER_STRING(mem_ctx,
5207 driver->default_datatype,
5208 r->default_datatype);
5210 result = string_array_from_driver_info(mem_ctx,
5211 driver->dependent_files,
5212 &r->dependent_files,
5213 cservername,
5214 driver->architecture,
5215 driver->version);
5216 if (!W_ERROR_IS_OK(result)) {
5217 return result;
5220 result = string_array_from_driver_info(mem_ctx,
5221 driver->previous_names,
5222 &r->previous_names,
5223 NULL, NULL, 0);
5224 if (!W_ERROR_IS_OK(result)) {
5225 return result;
5228 r->driver_date = driver->driver_date;
5229 r->driver_version = driver->driver_version;
5231 FILL_DRIVER_STRING(mem_ctx,
5232 driver->manufacturer_name,
5233 r->manufacturer_name);
5234 FILL_DRIVER_STRING(mem_ctx,
5235 driver->manufacturer_url,
5236 r->manufacturer_url);
5237 FILL_DRIVER_STRING(mem_ctx,
5238 driver->hardware_id,
5239 r->hardware_id);
5240 FILL_DRIVER_STRING(mem_ctx,
5241 driver->provider,
5242 r->provider);
5244 FILL_DRIVER_STRING(mem_ctx,
5245 driver->print_processor,
5246 r->print_processor);
5247 FILL_DRIVER_STRING(mem_ctx,
5248 driver->vendor_setup,
5249 r->vendor_setup);
5251 result = string_array_from_driver_info(mem_ctx,
5252 driver->color_profiles,
5253 &r->color_profiles,
5254 NULL, NULL, 0);
5255 if (!W_ERROR_IS_OK(result)) {
5256 return result;
5259 FILL_DRIVER_STRING(mem_ctx,
5260 driver->inf_path,
5261 r->inf_path);
5263 r->printer_driver_attributes = driver->printer_driver_attributes;
5265 result = string_array_from_driver_info(mem_ctx,
5266 driver->core_driver_dependencies,
5267 &r->core_driver_dependencies,
5268 NULL, NULL, 0);
5269 if (!W_ERROR_IS_OK(result)) {
5270 return result;
5273 r->min_inbox_driver_ver_date = driver->min_inbox_driver_ver_date;
5274 r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5276 return WERR_OK;
5279 #if 0 /* disabled until marshalling issues are resolved - gd */
5280 /********************************************************************
5281 ********************************************************************/
5283 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5284 struct spoolss_DriverFileInfo *r,
5285 const char *cservername,
5286 const char *file_name,
5287 enum spoolss_DriverFileType file_type,
5288 uint32_t file_version)
5290 r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
5291 cservername, file_name);
5292 W_ERROR_HAVE_NO_MEMORY(r->file_name);
5293 r->file_type = file_type;
5294 r->file_version = file_version;
5296 return WERR_OK;
5299 /********************************************************************
5300 ********************************************************************/
5302 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5303 const struct spoolss_DriverInfo8 *driver,
5304 const char *cservername,
5305 struct spoolss_DriverFileInfo **info_p,
5306 uint32_t *count_p)
5308 struct spoolss_DriverFileInfo *info = NULL;
5309 uint32_t count = 0;
5310 WERROR result;
5311 uint32_t i;
5313 *info_p = NULL;
5314 *count_p = 0;
5316 if (strlen(driver->driver_path)) {
5317 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5318 struct spoolss_DriverFileInfo,
5319 count + 1);
5320 W_ERROR_HAVE_NO_MEMORY(info);
5321 result = fill_spoolss_DriverFileInfo(info,
5322 &info[count],
5323 cservername,
5324 driver->driver_path,
5325 SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5327 W_ERROR_NOT_OK_RETURN(result);
5328 count++;
5331 if (strlen(driver->config_file)) {
5332 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5333 struct spoolss_DriverFileInfo,
5334 count + 1);
5335 W_ERROR_HAVE_NO_MEMORY(info);
5336 result = fill_spoolss_DriverFileInfo(info,
5337 &info[count],
5338 cservername,
5339 driver->config_file,
5340 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5342 W_ERROR_NOT_OK_RETURN(result);
5343 count++;
5346 if (strlen(driver->data_file)) {
5347 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5348 struct spoolss_DriverFileInfo,
5349 count + 1);
5350 W_ERROR_HAVE_NO_MEMORY(info);
5351 result = fill_spoolss_DriverFileInfo(info,
5352 &info[count],
5353 cservername,
5354 driver->data_file,
5355 SPOOLSS_DRIVER_FILE_TYPE_DATA,
5357 W_ERROR_NOT_OK_RETURN(result);
5358 count++;
5361 if (strlen(driver->help_file)) {
5362 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5363 struct spoolss_DriverFileInfo,
5364 count + 1);
5365 W_ERROR_HAVE_NO_MEMORY(info);
5366 result = fill_spoolss_DriverFileInfo(info,
5367 &info[count],
5368 cservername,
5369 driver->help_file,
5370 SPOOLSS_DRIVER_FILE_TYPE_HELP,
5372 W_ERROR_NOT_OK_RETURN(result);
5373 count++;
5376 for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5377 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5378 struct spoolss_DriverFileInfo,
5379 count + 1);
5380 W_ERROR_HAVE_NO_MEMORY(info);
5381 result = fill_spoolss_DriverFileInfo(info,
5382 &info[count],
5383 cservername,
5384 driver->dependent_files[i],
5385 SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5387 W_ERROR_NOT_OK_RETURN(result);
5388 count++;
5391 *info_p = info;
5392 *count_p = count;
5394 return WERR_OK;
5397 /********************************************************************
5398 * fill a spoolss_DriverInfo101 struct
5399 ********************************************************************/
5401 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5402 struct spoolss_DriverInfo101 *r,
5403 const struct spoolss_DriverInfo8 *driver,
5404 const char *servername)
5406 const char *cservername = canon_servername(servername);
5407 WERROR result;
5409 r->version = driver->version;
5411 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5412 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5413 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5414 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5416 result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5417 cservername,
5418 &r->file_info,
5419 &r->file_count);
5420 if (!W_ERROR_IS_OK(result)) {
5421 return result;
5424 FILL_DRIVER_STRING(mem_ctx,
5425 driver->monitor_name,
5426 r->monitor_name);
5428 FILL_DRIVER_STRING(mem_ctx,
5429 driver->default_datatype,
5430 r->default_datatype);
5432 result = string_array_from_driver_info(mem_ctx,
5433 driver->previous_names,
5434 &r->previous_names,
5435 NULL, NULL, 0);
5436 if (!W_ERROR_IS_OK(result)) {
5437 return result;
5440 r->driver_date = driver->driver_date;
5441 r->driver_version = driver->driver_version;
5443 FILL_DRIVER_STRING(mem_ctx,
5444 driver->manufacturer_name,
5445 r->manufacturer_name);
5446 FILL_DRIVER_STRING(mem_ctx,
5447 driver->manufacturer_url,
5448 r->manufacturer_url);
5449 FILL_DRIVER_STRING(mem_ctx,
5450 driver->hardware_id,
5451 r->hardware_id);
5452 FILL_DRIVER_STRING(mem_ctx,
5453 driver->provider,
5454 r->provider);
5456 return WERR_OK;
5458 #endif
5459 /********************************************************************
5460 ********************************************************************/
5462 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5463 const struct auth_serversupplied_info *session_info,
5464 struct messaging_context *msg_ctx,
5465 uint32_t level,
5466 union spoolss_DriverInfo *r,
5467 int snum,
5468 const char *servername,
5469 const char *architecture,
5470 uint32_t version)
5472 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5473 struct spoolss_DriverInfo8 *driver;
5474 WERROR result;
5476 if (level == 101) {
5477 return WERR_UNKNOWN_LEVEL;
5480 result = winreg_get_printer(mem_ctx,
5481 session_info,
5482 msg_ctx,
5483 lp_const_servicename(snum),
5484 &pinfo2);
5486 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5487 win_errstr(result)));
5489 if (!W_ERROR_IS_OK(result)) {
5490 return WERR_INVALID_PRINTER_NAME;
5493 result = winreg_get_driver(mem_ctx, session_info, msg_ctx,
5494 architecture,
5495 pinfo2->drivername, version, &driver);
5497 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5498 win_errstr(result)));
5500 if (!W_ERROR_IS_OK(result)) {
5502 * Is this a W2k client ?
5505 if (version < 3) {
5506 talloc_free(pinfo2);
5507 return WERR_UNKNOWN_PRINTER_DRIVER;
5510 /* Yes - try again with a WinNT driver. */
5511 version = 2;
5512 result = winreg_get_driver(mem_ctx, session_info, msg_ctx,
5513 architecture,
5514 pinfo2->drivername,
5515 version, &driver);
5516 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5517 win_errstr(result)));
5518 if (!W_ERROR_IS_OK(result)) {
5519 talloc_free(pinfo2);
5520 return WERR_UNKNOWN_PRINTER_DRIVER;
5524 switch (level) {
5525 case 1:
5526 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5527 break;
5528 case 2:
5529 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5530 break;
5531 case 3:
5532 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5533 break;
5534 case 4:
5535 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5536 break;
5537 case 5:
5538 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5539 break;
5540 case 6:
5541 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5542 break;
5543 case 8:
5544 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5545 break;
5546 #if 0 /* disabled until marshalling issues are resolved - gd */
5547 case 101:
5548 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5549 break;
5550 #endif
5551 default:
5552 result = WERR_UNKNOWN_LEVEL;
5553 break;
5556 talloc_free(pinfo2);
5557 talloc_free(driver);
5559 return result;
5562 /****************************************************************
5563 _spoolss_GetPrinterDriver2
5564 ****************************************************************/
5566 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5567 struct spoolss_GetPrinterDriver2 *r)
5569 struct printer_handle *printer;
5570 WERROR result;
5572 int snum;
5574 /* that's an [in out] buffer */
5576 if (!r->in.buffer && (r->in.offered != 0)) {
5577 return WERR_INVALID_PARAM;
5580 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5582 if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5583 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5584 return WERR_INVALID_PRINTER_NAME;
5587 *r->out.needed = 0;
5588 *r->out.server_major_version = 0;
5589 *r->out.server_minor_version = 0;
5591 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5592 return WERR_BADFID;
5595 result = construct_printer_driver_info_level(p->mem_ctx,
5596 get_session_info_system(),
5597 p->msg_ctx,
5598 r->in.level, r->out.info,
5599 snum, printer->servername,
5600 r->in.architecture,
5601 r->in.client_major_version);
5602 if (!W_ERROR_IS_OK(result)) {
5603 TALLOC_FREE(r->out.info);
5604 return result;
5607 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5608 r->out.info, r->in.level);
5609 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5611 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5615 /****************************************************************
5616 _spoolss_StartPagePrinter
5617 ****************************************************************/
5619 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5620 struct spoolss_StartPagePrinter *r)
5622 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5624 if (!Printer) {
5625 DEBUG(3,("_spoolss_StartPagePrinter: "
5626 "Error in startpageprinter printer handle\n"));
5627 return WERR_BADFID;
5630 Printer->page_started = true;
5631 return WERR_OK;
5634 /****************************************************************
5635 _spoolss_EndPagePrinter
5636 ****************************************************************/
5638 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5639 struct spoolss_EndPagePrinter *r)
5641 int snum;
5643 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5645 if (!Printer) {
5646 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5647 OUR_HANDLE(r->in.handle)));
5648 return WERR_BADFID;
5651 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5652 return WERR_BADFID;
5654 Printer->page_started = false;
5655 print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5657 return WERR_OK;
5660 /****************************************************************
5661 _spoolss_StartDocPrinter
5662 ****************************************************************/
5664 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5665 struct spoolss_StartDocPrinter *r)
5667 struct spoolss_DocumentInfo1 *info_1;
5668 int snum;
5669 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5670 WERROR werr;
5672 if (!Printer) {
5673 DEBUG(2,("_spoolss_StartDocPrinter: "
5674 "Invalid handle (%s:%u:%u)\n",
5675 OUR_HANDLE(r->in.handle)));
5676 return WERR_BADFID;
5679 if (Printer->jobid) {
5680 DEBUG(2, ("_spoolss_StartDocPrinter: "
5681 "StartDocPrinter called twice! "
5682 "(existing jobid = %d)\n", Printer->jobid));
5683 return WERR_INVALID_HANDLE;
5686 if (r->in.level != 1) {
5687 return WERR_UNKNOWN_LEVEL;
5690 info_1 = r->in.info.info1;
5693 * a nice thing with NT is it doesn't listen to what you tell it.
5694 * when asked to send _only_ RAW datas, it tries to send datas
5695 * in EMF format.
5697 * So I add checks like in NT Server ...
5700 if (info_1->datatype) {
5701 if (strcmp(info_1->datatype, "RAW") != 0) {
5702 *r->out.job_id = 0;
5703 return WERR_INVALID_DATATYPE;
5707 /* get the share number of the printer */
5708 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5709 return WERR_BADFID;
5712 werr = print_job_start(p->session_info,
5713 p->msg_ctx,
5714 p->client_id->name,
5715 snum,
5716 info_1->document_name,
5717 info_1->output_file,
5718 Printer->devmode,
5719 &Printer->jobid);
5721 /* An error occured in print_job_start() so return an appropriate
5722 NT error code. */
5724 if (!W_ERROR_IS_OK(werr)) {
5725 return werr;
5728 Printer->document_started = true;
5729 *r->out.job_id = Printer->jobid;
5731 return WERR_OK;
5734 /****************************************************************
5735 _spoolss_EndDocPrinter
5736 ****************************************************************/
5738 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5739 struct spoolss_EndDocPrinter *r)
5741 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5742 NTSTATUS status;
5743 int snum;
5745 if (!Printer) {
5746 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5747 OUR_HANDLE(r->in.handle)));
5748 return WERR_BADFID;
5751 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5752 return WERR_BADFID;
5755 Printer->document_started = false;
5756 status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5757 if (!NT_STATUS_IS_OK(status)) {
5758 DEBUG(2, ("_spoolss_EndDocPrinter: "
5759 "print_job_end failed [%s]\n",
5760 nt_errstr(status)));
5763 Printer->jobid = 0;
5764 return ntstatus_to_werror(status);
5767 /****************************************************************
5768 _spoolss_WritePrinter
5769 ****************************************************************/
5771 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5772 struct spoolss_WritePrinter *r)
5774 ssize_t buffer_written;
5775 int snum;
5776 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5778 if (!Printer) {
5779 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5780 OUR_HANDLE(r->in.handle)));
5781 *r->out.num_written = r->in._data_size;
5782 return WERR_BADFID;
5785 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5786 return WERR_BADFID;
5788 /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5789 buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5790 snum, Printer->jobid,
5791 (const char *)r->in.data.data,
5792 (size_t)r->in._data_size);
5793 if (buffer_written == (ssize_t)-1) {
5794 *r->out.num_written = 0;
5795 if (errno == ENOSPC)
5796 return WERR_NO_SPOOL_SPACE;
5797 else
5798 return WERR_ACCESS_DENIED;
5801 *r->out.num_written = r->in._data_size;
5803 return WERR_OK;
5806 /********************************************************************
5807 * api_spoolss_getprinter
5808 * called from the spoolss dispatcher
5810 ********************************************************************/
5812 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5813 struct pipes_struct *p)
5815 const struct auth_serversupplied_info *session_info = p->session_info;
5816 int snum;
5817 WERROR errcode = WERR_BADFUNC;
5818 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5820 if (!Printer) {
5821 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5822 OUR_HANDLE(handle)));
5823 return WERR_BADFID;
5826 if (!get_printer_snum(p, handle, &snum, NULL))
5827 return WERR_BADFID;
5829 switch (command) {
5830 case SPOOLSS_PRINTER_CONTROL_PAUSE:
5831 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
5832 break;
5833 case SPOOLSS_PRINTER_CONTROL_RESUME:
5834 case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5835 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
5836 break;
5837 case SPOOLSS_PRINTER_CONTROL_PURGE:
5838 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
5839 break;
5840 default:
5841 return WERR_UNKNOWN_LEVEL;
5844 return errcode;
5848 /****************************************************************
5849 _spoolss_AbortPrinter
5850 * From MSDN: "Deletes printer's spool file if printer is configured
5851 * for spooling"
5852 ****************************************************************/
5854 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
5855 struct spoolss_AbortPrinter *r)
5857 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5858 int snum;
5859 WERROR errcode = WERR_OK;
5861 if (!Printer) {
5862 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5863 OUR_HANDLE(r->in.handle)));
5864 return WERR_BADFID;
5867 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5868 return WERR_BADFID;
5870 if (!Printer->document_started) {
5871 return WERR_SPL_NO_STARTDOC;
5874 errcode = print_job_delete(p->session_info,
5875 p->msg_ctx,
5876 snum,
5877 Printer->jobid);
5879 return errcode;
5882 /********************************************************************
5883 * called by spoolss_api_setprinter
5884 * when updating a printer description
5885 ********************************************************************/
5887 static WERROR update_printer_sec(struct policy_handle *handle,
5888 struct pipes_struct *p,
5889 struct sec_desc_buf *secdesc_ctr)
5891 struct spoolss_security_descriptor *new_secdesc = NULL;
5892 struct spoolss_security_descriptor *old_secdesc = NULL;
5893 const char *printer;
5894 WERROR result;
5895 int snum;
5897 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5899 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5900 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5901 OUR_HANDLE(handle)));
5903 result = WERR_BADFID;
5904 goto done;
5907 if (secdesc_ctr == NULL) {
5908 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5909 result = WERR_INVALID_PARAM;
5910 goto done;
5912 printer = lp_const_servicename(snum);
5914 /* Check the user has permissions to change the security
5915 descriptor. By experimentation with two NT machines, the user
5916 requires Full Access to the printer to change security
5917 information. */
5919 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5920 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5921 result = WERR_ACCESS_DENIED;
5922 goto done;
5925 /* NT seems to like setting the security descriptor even though
5926 nothing may have actually changed. */
5927 result = winreg_get_printer_secdesc(p->mem_ctx,
5928 get_session_info_system(),
5929 p->msg_ctx,
5930 printer,
5931 &old_secdesc);
5932 if (!W_ERROR_IS_OK(result)) {
5933 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc() failed\n"));
5934 result = WERR_BADFID;
5935 goto done;
5938 if (DEBUGLEVEL >= 10) {
5939 struct security_acl *the_acl;
5940 int i;
5942 the_acl = old_secdesc->dacl;
5943 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5944 printer, the_acl->num_aces));
5946 for (i = 0; i < the_acl->num_aces; i++) {
5947 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5948 &the_acl->aces[i].trustee),
5949 the_acl->aces[i].access_mask));
5952 the_acl = secdesc_ctr->sd->dacl;
5954 if (the_acl) {
5955 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5956 printer, the_acl->num_aces));
5958 for (i = 0; i < the_acl->num_aces; i++) {
5959 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5960 &the_acl->aces[i].trustee),
5961 the_acl->aces[i].access_mask));
5963 } else {
5964 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5968 new_secdesc = sec_desc_merge(p->mem_ctx, secdesc_ctr->sd, old_secdesc);
5969 if (new_secdesc == NULL) {
5970 result = WERR_NOMEM;
5971 goto done;
5974 if (security_descriptor_equal(new_secdesc, old_secdesc)) {
5975 result = WERR_OK;
5976 goto done;
5979 result = winreg_set_printer_secdesc(p->mem_ctx,
5980 get_session_info_system(),
5981 p->msg_ctx,
5982 printer,
5983 new_secdesc);
5985 done:
5986 return result;
5989 /********************************************************************
5990 Canonicalize printer info from a client
5991 ********************************************************************/
5993 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
5994 struct spoolss_SetPrinterInfo2 *info2,
5995 int snum)
5997 fstring printername;
5998 const char *p;
6000 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6001 "portname=%s drivername=%s comment=%s location=%s\n",
6002 info2->servername, info2->printername, info2->sharename,
6003 info2->portname, info2->drivername, info2->comment,
6004 info2->location));
6006 /* we force some elements to "correct" values */
6007 info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
6008 if (info2->servername == NULL) {
6009 return false;
6011 info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6012 if (info2->sharename == NULL) {
6013 return false;
6016 /* check to see if we allow printername != sharename */
6017 if (lp_force_printername(snum)) {
6018 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6019 global_myname(), info2->sharename);
6020 } else {
6021 /* make sure printername is in \\server\printername format */
6022 fstrcpy(printername, info2->printername);
6023 p = printername;
6024 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6025 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6026 p++;
6029 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6030 global_myname(), p);
6032 if (info2->printername == NULL) {
6033 return false;
6036 info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6037 info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6039 return true;
6042 /****************************************************************************
6043 ****************************************************************************/
6045 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6047 char *cmd = lp_addport_cmd();
6048 char *command = NULL;
6049 int ret;
6050 bool is_print_op = false;
6052 if ( !*cmd ) {
6053 return WERR_ACCESS_DENIED;
6056 command = talloc_asprintf(ctx,
6057 "%s \"%s\" \"%s\"", cmd, portname, uri );
6058 if (!command) {
6059 return WERR_NOMEM;
6062 if ( token )
6063 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6065 DEBUG(10,("Running [%s]\n", command));
6067 /********* BEGIN SePrintOperatorPrivilege **********/
6069 if ( is_print_op )
6070 become_root();
6072 ret = smbrun(command, NULL);
6074 if ( is_print_op )
6075 unbecome_root();
6077 /********* END SePrintOperatorPrivilege **********/
6079 DEBUGADD(10,("returned [%d]\n", ret));
6081 TALLOC_FREE(command);
6083 if ( ret != 0 ) {
6084 return WERR_ACCESS_DENIED;
6087 return WERR_OK;
6090 /****************************************************************************
6091 ****************************************************************************/
6093 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6094 struct spoolss_SetPrinterInfo2 *info2,
6095 const char *remote_machine,
6096 struct messaging_context *msg_ctx)
6098 char *cmd = lp_addprinter_cmd();
6099 char **qlines;
6100 char *command = NULL;
6101 int numlines;
6102 int ret;
6103 int fd;
6104 bool is_print_op = false;
6106 if (!remote_machine) {
6107 return false;
6110 command = talloc_asprintf(ctx,
6111 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6112 cmd, info2->printername, info2->sharename,
6113 info2->portname, info2->drivername,
6114 info2->location, info2->comment, remote_machine);
6115 if (!command) {
6116 return false;
6119 if ( token )
6120 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6122 DEBUG(10,("Running [%s]\n", command));
6124 /********* BEGIN SePrintOperatorPrivilege **********/
6126 if ( is_print_op )
6127 become_root();
6129 if ( (ret = smbrun(command, &fd)) == 0 ) {
6130 /* Tell everyone we updated smb.conf. */
6131 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6134 if ( is_print_op )
6135 unbecome_root();
6137 /********* END SePrintOperatorPrivilege **********/
6139 DEBUGADD(10,("returned [%d]\n", ret));
6141 TALLOC_FREE(command);
6143 if ( ret != 0 ) {
6144 if (fd != -1)
6145 close(fd);
6146 return false;
6149 /* reload our services immediately */
6150 become_root();
6151 reload_services(msg_ctx, -1, false);
6152 unbecome_root();
6154 numlines = 0;
6155 /* Get lines and convert them back to dos-codepage */
6156 qlines = fd_lines_load(fd, &numlines, 0, NULL);
6157 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6158 close(fd);
6160 /* Set the portname to what the script says the portname should be. */
6161 /* but don't require anything to be return from the script exit a good error code */
6163 if (numlines) {
6164 /* Set the portname to what the script says the portname should be. */
6165 info2->portname = talloc_strdup(ctx, qlines[0]);
6166 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6169 TALLOC_FREE(qlines);
6170 return true;
6173 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6174 const struct auth_serversupplied_info *session_info,
6175 struct messaging_context *msg_ctx,
6176 int snum,
6177 struct spoolss_SetPrinterInfo2 *printer,
6178 struct spoolss_PrinterInfo2 *old_printer)
6180 bool force_update = (old_printer == NULL);
6181 const char *dnsdomname;
6182 const char *longname;
6183 const char *uncname;
6184 const char *spooling;
6185 DATA_BLOB buffer;
6186 WERROR result = WERR_OK;
6188 if (force_update || !strequal(printer->drivername, old_printer->drivername)) {
6189 push_reg_sz(mem_ctx, &buffer, printer->drivername);
6190 winreg_set_printer_dataex(mem_ctx,
6191 session_info,
6192 msg_ctx,
6193 printer->sharename,
6194 SPOOL_DSSPOOLER_KEY,
6195 SPOOL_REG_DRIVERNAME,
6196 REG_SZ,
6197 buffer.data,
6198 buffer.length);
6200 if (!force_update) {
6201 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6202 printer->drivername));
6204 notify_printer_driver(server_event_context(), msg_ctx,
6205 snum, printer->drivername ?
6206 printer->drivername : "");
6210 if (force_update || !strequal(printer->comment, old_printer->comment)) {
6211 push_reg_sz(mem_ctx, &buffer, printer->comment);
6212 winreg_set_printer_dataex(mem_ctx,
6213 session_info,
6214 msg_ctx,
6215 printer->sharename,
6216 SPOOL_DSSPOOLER_KEY,
6217 SPOOL_REG_DESCRIPTION,
6218 REG_SZ,
6219 buffer.data,
6220 buffer.length);
6222 if (!force_update) {
6223 notify_printer_comment(server_event_context(), msg_ctx,
6224 snum, printer->comment ?
6225 printer->comment : "");
6229 if (force_update || !strequal(printer->sharename, old_printer->sharename)) {
6230 push_reg_sz(mem_ctx, &buffer, printer->sharename);
6231 winreg_set_printer_dataex(mem_ctx,
6232 session_info,
6233 msg_ctx,
6234 printer->sharename,
6235 SPOOL_DSSPOOLER_KEY,
6236 SPOOL_REG_PRINTSHARENAME,
6237 REG_SZ,
6238 buffer.data,
6239 buffer.length);
6241 if (!force_update) {
6242 notify_printer_sharename(server_event_context(),
6243 msg_ctx,
6244 snum, printer->sharename ?
6245 printer->sharename : "");
6249 if (force_update || !strequal(printer->printername, old_printer->printername)) {
6250 const char *p;
6252 p = strrchr(printer->printername, '\\' );
6253 if (p != NULL) {
6254 p++;
6255 } else {
6256 p = printer->printername;
6259 push_reg_sz(mem_ctx, &buffer, p);
6260 winreg_set_printer_dataex(mem_ctx,
6261 session_info,
6262 msg_ctx,
6263 printer->sharename,
6264 SPOOL_DSSPOOLER_KEY,
6265 SPOOL_REG_PRINTERNAME,
6266 REG_SZ,
6267 buffer.data,
6268 buffer.length);
6270 if (!force_update) {
6271 notify_printer_printername(server_event_context(),
6272 msg_ctx, snum, p ? p : "");
6276 if (force_update || !strequal(printer->portname, old_printer->portname)) {
6277 push_reg_sz(mem_ctx, &buffer, printer->portname);
6278 winreg_set_printer_dataex(mem_ctx,
6279 session_info,
6280 msg_ctx,
6281 printer->sharename,
6282 SPOOL_DSSPOOLER_KEY,
6283 SPOOL_REG_PORTNAME,
6284 REG_SZ,
6285 buffer.data,
6286 buffer.length);
6288 if (!force_update) {
6289 notify_printer_port(server_event_context(),
6290 msg_ctx, snum, printer->portname ?
6291 printer->portname : "");
6295 if (force_update || !strequal(printer->location, old_printer->location)) {
6296 push_reg_sz(mem_ctx, &buffer, printer->location);
6297 winreg_set_printer_dataex(mem_ctx,
6298 session_info,
6299 msg_ctx,
6300 printer->sharename,
6301 SPOOL_DSSPOOLER_KEY,
6302 SPOOL_REG_LOCATION,
6303 REG_SZ,
6304 buffer.data,
6305 buffer.length);
6307 if (!force_update) {
6308 notify_printer_location(server_event_context(),
6309 msg_ctx, snum,
6310 printer->location ?
6311 printer->location : "");
6315 if (force_update || !strequal(printer->sepfile, old_printer->sepfile)) {
6316 push_reg_sz(mem_ctx, &buffer, printer->sepfile);
6317 winreg_set_printer_dataex(mem_ctx,
6318 session_info,
6319 msg_ctx,
6320 printer->sharename,
6321 SPOOL_DSSPOOLER_KEY,
6322 SPOOL_REG_PRINTSEPARATORFILE,
6323 REG_SZ,
6324 buffer.data,
6325 buffer.length);
6327 if (!force_update) {
6328 notify_printer_sepfile(server_event_context(),
6329 msg_ctx, snum,
6330 printer->sepfile ?
6331 printer->sepfile : "");
6335 if (force_update || printer->starttime != old_printer->starttime) {
6336 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6337 SIVAL(buffer.data, 0, printer->starttime);
6338 winreg_set_printer_dataex(mem_ctx,
6339 session_info,
6340 msg_ctx,
6341 printer->sharename,
6342 SPOOL_DSSPOOLER_KEY,
6343 SPOOL_REG_PRINTSTARTTIME,
6344 REG_DWORD,
6345 buffer.data,
6346 buffer.length);
6349 if (force_update || printer->untiltime != old_printer->untiltime) {
6350 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6351 SIVAL(buffer.data, 0, printer->untiltime);
6352 winreg_set_printer_dataex(mem_ctx,
6353 session_info,
6354 msg_ctx,
6355 printer->sharename,
6356 SPOOL_DSSPOOLER_KEY,
6357 SPOOL_REG_PRINTENDTIME,
6358 REG_DWORD,
6359 buffer.data,
6360 buffer.length);
6363 if (force_update || printer->priority != old_printer->priority) {
6364 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6365 SIVAL(buffer.data, 0, printer->priority);
6366 winreg_set_printer_dataex(mem_ctx,
6367 session_info,
6368 msg_ctx,
6369 printer->sharename,
6370 SPOOL_DSSPOOLER_KEY,
6371 SPOOL_REG_PRIORITY,
6372 REG_DWORD,
6373 buffer.data,
6374 buffer.length);
6377 if (force_update || printer->attributes != old_printer->attributes) {
6378 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6379 SIVAL(buffer.data, 0, (printer->attributes &
6380 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6381 winreg_set_printer_dataex(mem_ctx,
6382 session_info,
6383 msg_ctx,
6384 printer->sharename,
6385 SPOOL_DSSPOOLER_KEY,
6386 SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6387 REG_DWORD,
6388 buffer.data,
6389 buffer.length);
6391 switch (printer->attributes & 0x3) {
6392 case 0:
6393 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6394 break;
6395 case 1:
6396 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6397 break;
6398 case 2:
6399 spooling = SPOOL_REGVAL_PRINTDIRECT;
6400 break;
6401 default:
6402 spooling = "unknown";
6404 push_reg_sz(mem_ctx, &buffer, spooling);
6405 winreg_set_printer_dataex(mem_ctx,
6406 session_info,
6407 msg_ctx,
6408 printer->sharename,
6409 SPOOL_DSSPOOLER_KEY,
6410 SPOOL_REG_PRINTSPOOLING,
6411 REG_SZ,
6412 buffer.data,
6413 buffer.length);
6416 push_reg_sz(mem_ctx, &buffer, global_myname());
6417 winreg_set_printer_dataex(mem_ctx,
6418 session_info,
6419 msg_ctx,
6420 printer->sharename,
6421 SPOOL_DSSPOOLER_KEY,
6422 SPOOL_REG_SHORTSERVERNAME,
6423 REG_SZ,
6424 buffer.data,
6425 buffer.length);
6427 dnsdomname = get_mydnsfullname();
6428 if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6429 longname = talloc_strdup(mem_ctx, dnsdomname);
6430 } else {
6431 longname = talloc_strdup(mem_ctx, global_myname());
6433 if (longname == NULL) {
6434 result = WERR_NOMEM;
6435 goto done;
6438 push_reg_sz(mem_ctx, &buffer, longname);
6439 winreg_set_printer_dataex(mem_ctx,
6440 session_info,
6441 msg_ctx,
6442 printer->sharename,
6443 SPOOL_DSSPOOLER_KEY,
6444 SPOOL_REG_SERVERNAME,
6445 REG_SZ,
6446 buffer.data,
6447 buffer.length);
6449 uncname = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6450 global_myname(), printer->sharename);
6451 push_reg_sz(mem_ctx, &buffer, uncname);
6452 winreg_set_printer_dataex(mem_ctx,
6453 session_info,
6454 msg_ctx,
6455 printer->sharename,
6456 SPOOL_DSSPOOLER_KEY,
6457 SPOOL_REG_UNCNAME,
6458 REG_SZ,
6459 buffer.data,
6460 buffer.length);
6462 done:
6463 return result;
6466 /********************************************************************
6467 * Called by spoolss_api_setprinter
6468 * when updating a printer description.
6469 ********************************************************************/
6471 static WERROR update_printer(struct pipes_struct *p,
6472 struct policy_handle *handle,
6473 struct spoolss_SetPrinterInfoCtr *info_ctr,
6474 struct spoolss_DeviceMode *devmode)
6476 uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6477 struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6478 struct spoolss_PrinterInfo2 *old_printer;
6479 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6480 int snum;
6481 WERROR result = WERR_OK;
6482 TALLOC_CTX *tmp_ctx;
6484 DEBUG(8,("update_printer\n"));
6486 tmp_ctx = talloc_new(p->mem_ctx);
6487 if (tmp_ctx == NULL) {
6488 return WERR_NOMEM;
6491 if (!Printer) {
6492 result = WERR_BADFID;
6493 goto done;
6496 if (!get_printer_snum(p, handle, &snum, NULL)) {
6497 result = WERR_BADFID;
6498 goto done;
6501 result = winreg_get_printer(tmp_ctx,
6502 get_session_info_system(),
6503 p->msg_ctx,
6504 lp_const_servicename(snum),
6505 &old_printer);
6506 if (!W_ERROR_IS_OK(result)) {
6507 result = WERR_BADFID;
6508 goto done;
6511 /* Do sanity check on the requested changes for Samba */
6512 if (!check_printer_ok(tmp_ctx, printer, snum)) {
6513 result = WERR_INVALID_PARAM;
6514 goto done;
6517 /* FIXME!!! If the driver has changed we really should verify that
6518 it is installed before doing much else --jerry */
6520 /* Check calling user has permission to update printer description */
6521 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6522 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6523 result = WERR_ACCESS_DENIED;
6524 goto done;
6527 /* Call addprinter hook */
6528 /* Check changes to see if this is really needed */
6530 if (*lp_addprinter_cmd() &&
6531 (!strequal(printer->drivername, old_printer->drivername) ||
6532 !strequal(printer->comment, old_printer->comment) ||
6533 !strequal(printer->portname, old_printer->portname) ||
6534 !strequal(printer->location, old_printer->location)) )
6536 /* add_printer_hook() will call reload_services() */
6537 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6538 printer, p->client_id->addr,
6539 p->msg_ctx)) {
6540 result = WERR_ACCESS_DENIED;
6541 goto done;
6545 update_dsspooler(tmp_ctx,
6546 get_session_info_system(),
6547 p->msg_ctx,
6548 snum,
6549 printer,
6550 old_printer);
6552 printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6554 if (devmode == NULL) {
6555 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6557 result = winreg_update_printer(tmp_ctx,
6558 get_session_info_system(),
6559 p->msg_ctx,
6560 printer->sharename,
6561 printer_mask,
6562 printer,
6563 devmode,
6564 NULL);
6566 done:
6567 talloc_free(tmp_ctx);
6569 return result;
6572 /****************************************************************************
6573 ****************************************************************************/
6574 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6575 struct policy_handle *handle,
6576 struct spoolss_SetPrinterInfo7 *info7)
6578 #ifdef HAVE_ADS
6579 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6580 WERROR result;
6581 int snum;
6582 struct printer_handle *Printer;
6584 if ( lp_security() != SEC_ADS ) {
6585 return WERR_UNKNOWN_LEVEL;
6588 Printer = find_printer_index_by_hnd(p, handle);
6590 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6592 if (!Printer)
6593 return WERR_BADFID;
6595 if (!get_printer_snum(p, handle, &snum, NULL))
6596 return WERR_BADFID;
6598 result = winreg_get_printer(p->mem_ctx,
6599 get_session_info_system(),
6600 p->msg_ctx,
6601 lp_servicename(snum),
6602 &pinfo2);
6603 if (!W_ERROR_IS_OK(result)) {
6604 return WERR_BADFID;
6607 nt_printer_publish(pinfo2,
6608 get_session_info_system(),
6609 p->msg_ctx,
6610 pinfo2,
6611 info7->action);
6613 TALLOC_FREE(pinfo2);
6614 return WERR_OK;
6615 #else
6616 return WERR_UNKNOWN_LEVEL;
6617 #endif
6620 /********************************************************************
6621 ********************************************************************/
6623 static WERROR update_printer_devmode(struct pipes_struct *p,
6624 struct policy_handle *handle,
6625 struct spoolss_DeviceMode *devmode)
6627 int snum;
6628 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6629 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6631 DEBUG(8,("update_printer_devmode\n"));
6633 if (!Printer) {
6634 return WERR_BADFID;
6637 if (!get_printer_snum(p, handle, &snum, NULL)) {
6638 return WERR_BADFID;
6641 /* Check calling user has permission to update printer description */
6642 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6643 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6644 return WERR_ACCESS_DENIED;
6647 return winreg_update_printer(p->mem_ctx,
6648 get_session_info_system(),
6649 p->msg_ctx,
6650 lp_const_servicename(snum),
6651 info2_mask,
6652 NULL,
6653 devmode,
6654 NULL);
6658 /****************************************************************
6659 _spoolss_SetPrinter
6660 ****************************************************************/
6662 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6663 struct spoolss_SetPrinter *r)
6665 WERROR result;
6667 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6669 if (!Printer) {
6670 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6671 OUR_HANDLE(r->in.handle)));
6672 return WERR_BADFID;
6675 /* check the level */
6676 switch (r->in.info_ctr->level) {
6677 case 0:
6678 return control_printer(r->in.handle, r->in.command, p);
6679 case 2:
6680 result = update_printer(p, r->in.handle,
6681 r->in.info_ctr,
6682 r->in.devmode_ctr->devmode);
6683 if (!W_ERROR_IS_OK(result))
6684 return result;
6685 if (r->in.secdesc_ctr->sd)
6686 result = update_printer_sec(r->in.handle, p,
6687 r->in.secdesc_ctr);
6688 return result;
6689 case 3:
6690 return update_printer_sec(r->in.handle, p,
6691 r->in.secdesc_ctr);
6692 case 7:
6693 return publish_or_unpublish_printer(p, r->in.handle,
6694 r->in.info_ctr->info.info7);
6695 case 8:
6696 return update_printer_devmode(p, r->in.handle,
6697 r->in.devmode_ctr->devmode);
6698 default:
6699 return WERR_UNKNOWN_LEVEL;
6703 /****************************************************************
6704 _spoolss_FindClosePrinterNotify
6705 ****************************************************************/
6707 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
6708 struct spoolss_FindClosePrinterNotify *r)
6710 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6712 if (!Printer) {
6713 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6714 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6715 return WERR_BADFID;
6718 if (Printer->notify.cli_chan != NULL &&
6719 Printer->notify.cli_chan->active_connections > 0) {
6720 int snum = -1;
6722 if (Printer->printer_type == SPLHND_PRINTER) {
6723 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6724 return WERR_BADFID;
6728 srv_spoolss_replycloseprinter(snum, Printer);
6731 Printer->notify.flags=0;
6732 Printer->notify.options=0;
6733 Printer->notify.localmachine[0]='\0';
6734 Printer->notify.printerlocal=0;
6735 TALLOC_FREE(Printer->notify.option);
6737 return WERR_OK;
6740 /****************************************************************
6741 _spoolss_AddJob
6742 ****************************************************************/
6744 WERROR _spoolss_AddJob(struct pipes_struct *p,
6745 struct spoolss_AddJob *r)
6747 if (!r->in.buffer && (r->in.offered != 0)) {
6748 return WERR_INVALID_PARAM;
6751 /* this is what a NT server returns for AddJob. AddJob must fail on
6752 * non-local printers */
6754 if (r->in.level != 1) {
6755 return WERR_UNKNOWN_LEVEL;
6758 return WERR_INVALID_PARAM;
6761 /****************************************************************************
6762 fill_job_info1
6763 ****************************************************************************/
6765 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6766 struct spoolss_JobInfo1 *r,
6767 const print_queue_struct *queue,
6768 int position, int snum,
6769 struct spoolss_PrinterInfo2 *pinfo2)
6771 struct tm *t;
6773 t = gmtime(&queue->time);
6775 r->job_id = queue->job;
6777 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6778 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6779 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
6780 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6781 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6782 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6783 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6784 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6785 r->data_type = talloc_strdup(mem_ctx, "RAW");
6786 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6787 r->text_status = talloc_strdup(mem_ctx, "");
6788 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6790 r->status = nt_printj_status(queue->status);
6791 r->priority = queue->priority;
6792 r->position = position;
6793 r->total_pages = queue->page_count;
6794 r->pages_printed = 0; /* ??? */
6796 init_systemtime(&r->submitted, t);
6798 return WERR_OK;
6801 /****************************************************************************
6802 fill_job_info2
6803 ****************************************************************************/
6805 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6806 struct spoolss_JobInfo2 *r,
6807 const print_queue_struct *queue,
6808 int position, int snum,
6809 struct spoolss_PrinterInfo2 *pinfo2,
6810 struct spoolss_DeviceMode *devmode)
6812 struct tm *t;
6814 t = gmtime(&queue->time);
6816 r->job_id = queue->job;
6818 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6819 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6820 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
6821 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6822 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6823 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6824 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6825 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6826 r->notify_name = talloc_strdup(mem_ctx, queue->fs_user);
6827 W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6828 r->data_type = talloc_strdup(mem_ctx, "RAW");
6829 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6830 r->print_processor = talloc_strdup(mem_ctx, "winprint");
6831 W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6832 r->parameters = talloc_strdup(mem_ctx, "");
6833 W_ERROR_HAVE_NO_MEMORY(r->parameters);
6834 r->driver_name = talloc_strdup(mem_ctx, pinfo2->drivername);
6835 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6837 r->devmode = devmode;
6839 r->text_status = talloc_strdup(mem_ctx, "");
6840 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6842 r->secdesc = NULL;
6844 r->status = nt_printj_status(queue->status);
6845 r->priority = queue->priority;
6846 r->position = position;
6847 r->start_time = 0;
6848 r->until_time = 0;
6849 r->total_pages = queue->page_count;
6850 r->size = queue->size;
6851 init_systemtime(&r->submitted, t);
6852 r->time = 0;
6853 r->pages_printed = 0; /* ??? */
6855 return WERR_OK;
6858 /****************************************************************************
6859 fill_job_info3
6860 ****************************************************************************/
6862 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6863 struct spoolss_JobInfo3 *r,
6864 const print_queue_struct *queue,
6865 const print_queue_struct *next_queue,
6866 int position, int snum,
6867 struct spoolss_PrinterInfo2 *pinfo2)
6869 r->job_id = queue->job;
6870 r->next_job_id = 0;
6871 if (next_queue) {
6872 r->next_job_id = next_queue->job;
6874 r->reserved = 0;
6876 return WERR_OK;
6879 /****************************************************************************
6880 Enumjobs at level 1.
6881 ****************************************************************************/
6883 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6884 const print_queue_struct *queue,
6885 uint32_t num_queues, int snum,
6886 struct spoolss_PrinterInfo2 *pinfo2,
6887 union spoolss_JobInfo **info_p,
6888 uint32_t *count)
6890 union spoolss_JobInfo *info;
6891 int i;
6892 WERROR result = WERR_OK;
6894 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6895 W_ERROR_HAVE_NO_MEMORY(info);
6897 *count = num_queues;
6899 for (i=0; i<*count; i++) {
6900 result = fill_job_info1(info,
6901 &info[i].info1,
6902 &queue[i],
6904 snum,
6905 pinfo2);
6906 if (!W_ERROR_IS_OK(result)) {
6907 goto out;
6911 out:
6912 if (!W_ERROR_IS_OK(result)) {
6913 TALLOC_FREE(info);
6914 *count = 0;
6915 return result;
6918 *info_p = info;
6920 return WERR_OK;
6923 /****************************************************************************
6924 Enumjobs at level 2.
6925 ****************************************************************************/
6927 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6928 const print_queue_struct *queue,
6929 uint32_t num_queues, int snum,
6930 struct spoolss_PrinterInfo2 *pinfo2,
6931 union spoolss_JobInfo **info_p,
6932 uint32_t *count)
6934 union spoolss_JobInfo *info;
6935 int i;
6936 WERROR result = WERR_OK;
6938 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6939 W_ERROR_HAVE_NO_MEMORY(info);
6941 *count = num_queues;
6943 for (i=0; i<*count; i++) {
6944 struct spoolss_DeviceMode *devmode;
6946 result = spoolss_create_default_devmode(info,
6947 pinfo2->printername,
6948 &devmode);
6949 if (!W_ERROR_IS_OK(result)) {
6950 DEBUG(3, ("Can't proceed w/o a devmode!"));
6951 goto out;
6954 result = fill_job_info2(info,
6955 &info[i].info2,
6956 &queue[i],
6958 snum,
6959 pinfo2,
6960 devmode);
6961 if (!W_ERROR_IS_OK(result)) {
6962 goto out;
6966 out:
6967 if (!W_ERROR_IS_OK(result)) {
6968 TALLOC_FREE(info);
6969 *count = 0;
6970 return result;
6973 *info_p = info;
6975 return WERR_OK;
6978 /****************************************************************************
6979 Enumjobs at level 3.
6980 ****************************************************************************/
6982 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
6983 const print_queue_struct *queue,
6984 uint32_t num_queues, int snum,
6985 struct spoolss_PrinterInfo2 *pinfo2,
6986 union spoolss_JobInfo **info_p,
6987 uint32_t *count)
6989 union spoolss_JobInfo *info;
6990 int i;
6991 WERROR result = WERR_OK;
6993 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6994 W_ERROR_HAVE_NO_MEMORY(info);
6996 *count = num_queues;
6998 for (i=0; i<*count; i++) {
6999 const print_queue_struct *next_queue = NULL;
7001 if (i+1 < *count) {
7002 next_queue = &queue[i+1];
7005 result = fill_job_info3(info,
7006 &info[i].info3,
7007 &queue[i],
7008 next_queue,
7010 snum,
7011 pinfo2);
7012 if (!W_ERROR_IS_OK(result)) {
7013 goto out;
7017 out:
7018 if (!W_ERROR_IS_OK(result)) {
7019 TALLOC_FREE(info);
7020 *count = 0;
7021 return result;
7024 *info_p = info;
7026 return WERR_OK;
7029 /****************************************************************
7030 _spoolss_EnumJobs
7031 ****************************************************************/
7033 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7034 struct spoolss_EnumJobs *r)
7036 WERROR result;
7037 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7038 int snum;
7039 print_status_struct prt_status;
7040 print_queue_struct *queue = NULL;
7041 uint32_t count;
7043 /* that's an [in out] buffer */
7045 if (!r->in.buffer && (r->in.offered != 0)) {
7046 return WERR_INVALID_PARAM;
7049 DEBUG(4,("_spoolss_EnumJobs\n"));
7051 *r->out.needed = 0;
7052 *r->out.count = 0;
7053 *r->out.info = NULL;
7055 /* lookup the printer snum and tdb entry */
7057 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7058 return WERR_BADFID;
7061 result = winreg_get_printer(p->mem_ctx,
7062 get_session_info_system(),
7063 p->msg_ctx,
7064 lp_const_servicename(snum),
7065 &pinfo2);
7066 if (!W_ERROR_IS_OK(result)) {
7067 return result;
7070 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7071 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7072 count, prt_status.status, prt_status.message));
7074 if (count == 0) {
7075 SAFE_FREE(queue);
7076 TALLOC_FREE(pinfo2);
7077 return WERR_OK;
7080 switch (r->in.level) {
7081 case 1:
7082 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7083 pinfo2, r->out.info, r->out.count);
7084 break;
7085 case 2:
7086 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7087 pinfo2, r->out.info, r->out.count);
7088 break;
7089 case 3:
7090 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7091 pinfo2, r->out.info, r->out.count);
7092 break;
7093 default:
7094 result = WERR_UNKNOWN_LEVEL;
7095 break;
7098 SAFE_FREE(queue);
7099 TALLOC_FREE(pinfo2);
7101 if (!W_ERROR_IS_OK(result)) {
7102 return result;
7105 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7106 spoolss_EnumJobs,
7107 *r->out.info, r->in.level,
7108 *r->out.count);
7109 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7110 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7112 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7115 /****************************************************************
7116 _spoolss_ScheduleJob
7117 ****************************************************************/
7119 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7120 struct spoolss_ScheduleJob *r)
7122 return WERR_OK;
7125 /****************************************************************
7126 ****************************************************************/
7128 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7129 struct messaging_context *msg_ctx,
7130 const char *printer_name,
7131 uint32_t job_id,
7132 struct spoolss_SetJobInfo1 *r)
7134 char *old_doc_name;
7136 if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7137 return WERR_BADFID;
7140 if (strequal(old_doc_name, r->document_name)) {
7141 return WERR_OK;
7144 if (!print_job_set_name(server_event_context(), msg_ctx,
7145 printer_name, job_id, r->document_name)) {
7146 return WERR_BADFID;
7149 return WERR_OK;
7152 /****************************************************************
7153 _spoolss_SetJob
7154 ****************************************************************/
7156 WERROR _spoolss_SetJob(struct pipes_struct *p,
7157 struct spoolss_SetJob *r)
7159 const struct auth_serversupplied_info *session_info = p->session_info;
7160 int snum;
7161 WERROR errcode = WERR_BADFUNC;
7163 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7164 return WERR_BADFID;
7167 if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7168 return WERR_INVALID_PRINTER_NAME;
7171 switch (r->in.command) {
7172 case SPOOLSS_JOB_CONTROL_CANCEL:
7173 case SPOOLSS_JOB_CONTROL_DELETE:
7174 errcode = print_job_delete(session_info, p->msg_ctx,
7175 snum, r->in.job_id);
7176 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7177 errcode = WERR_OK;
7179 break;
7180 case SPOOLSS_JOB_CONTROL_PAUSE:
7181 if (print_job_pause(session_info, p->msg_ctx,
7182 snum, r->in.job_id, &errcode)) {
7183 errcode = WERR_OK;
7185 break;
7186 case SPOOLSS_JOB_CONTROL_RESTART:
7187 case SPOOLSS_JOB_CONTROL_RESUME:
7188 if (print_job_resume(session_info, p->msg_ctx,
7189 snum, r->in.job_id, &errcode)) {
7190 errcode = WERR_OK;
7192 break;
7193 case 0:
7194 errcode = WERR_OK;
7195 break;
7196 default:
7197 return WERR_UNKNOWN_LEVEL;
7200 if (!W_ERROR_IS_OK(errcode)) {
7201 return errcode;
7204 if (r->in.ctr == NULL) {
7205 return errcode;
7208 switch (r->in.ctr->level) {
7209 case 1:
7210 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7211 lp_const_servicename(snum),
7212 r->in.job_id,
7213 r->in.ctr->info.info1);
7214 break;
7215 case 2:
7216 case 3:
7217 case 4:
7218 default:
7219 return WERR_UNKNOWN_LEVEL;
7222 return errcode;
7225 /****************************************************************************
7226 Enumerates all printer drivers by level and architecture.
7227 ****************************************************************************/
7229 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7230 const struct auth_serversupplied_info *session_info,
7231 struct messaging_context *msg_ctx,
7232 const char *servername,
7233 const char *architecture,
7234 uint32_t level,
7235 union spoolss_DriverInfo **info_p,
7236 uint32_t *count_p)
7238 int i;
7239 uint32_t version;
7240 struct spoolss_DriverInfo8 *driver;
7241 union spoolss_DriverInfo *info = NULL;
7242 uint32_t count = 0;
7243 WERROR result = WERR_OK;
7244 uint32_t num_drivers;
7245 const char **drivers;
7247 *count_p = 0;
7248 *info_p = NULL;
7250 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7251 result = winreg_get_driver_list(mem_ctx, session_info, msg_ctx,
7252 architecture, version,
7253 &num_drivers, &drivers);
7254 if (!W_ERROR_IS_OK(result)) {
7255 goto out;
7257 DEBUG(4, ("we have:[%d] drivers in environment"
7258 " [%s] and version [%d]\n",
7259 num_drivers, architecture, version));
7261 if (num_drivers != 0) {
7262 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
7263 union spoolss_DriverInfo,
7264 count + num_drivers);
7265 if (!info) {
7266 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7267 "failed to enlarge driver info buffer!\n"));
7268 result = WERR_NOMEM;
7269 goto out;
7273 for (i = 0; i < num_drivers; i++) {
7274 DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7276 result = winreg_get_driver(mem_ctx, session_info,
7277 msg_ctx,
7278 architecture, drivers[i],
7279 version, &driver);
7280 if (!W_ERROR_IS_OK(result)) {
7281 goto out;
7284 switch (level) {
7285 case 1:
7286 result = fill_printer_driver_info1(info, &info[count+i].info1,
7287 driver, servername);
7288 break;
7289 case 2:
7290 result = fill_printer_driver_info2(info, &info[count+i].info2,
7291 driver, servername);
7292 break;
7293 case 3:
7294 result = fill_printer_driver_info3(info, &info[count+i].info3,
7295 driver, servername);
7296 break;
7297 case 4:
7298 result = fill_printer_driver_info4(info, &info[count+i].info4,
7299 driver, servername);
7300 break;
7301 case 5:
7302 result = fill_printer_driver_info5(info, &info[count+i].info5,
7303 driver, servername);
7304 break;
7305 case 6:
7306 result = fill_printer_driver_info6(info, &info[count+i].info6,
7307 driver, servername);
7308 break;
7309 case 8:
7310 result = fill_printer_driver_info8(info, &info[count+i].info8,
7311 driver, servername);
7312 break;
7313 default:
7314 result = WERR_UNKNOWN_LEVEL;
7315 break;
7318 TALLOC_FREE(driver);
7320 if (!W_ERROR_IS_OK(result)) {
7321 goto out;
7325 count += num_drivers;
7326 TALLOC_FREE(drivers);
7329 out:
7330 TALLOC_FREE(drivers);
7332 if (!W_ERROR_IS_OK(result)) {
7333 TALLOC_FREE(info);
7334 return result;
7337 *info_p = info;
7338 *count_p = count;
7340 return WERR_OK;
7343 /****************************************************************************
7344 Enumerates all printer drivers by level.
7345 ****************************************************************************/
7347 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7348 const struct auth_serversupplied_info *session_info,
7349 struct messaging_context *msg_ctx,
7350 const char *servername,
7351 const char *architecture,
7352 uint32_t level,
7353 union spoolss_DriverInfo **info_p,
7354 uint32_t *count_p)
7356 uint32_t a,i;
7357 WERROR result = WERR_OK;
7359 if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7361 for (a=0; archi_table[a].long_archi != NULL; a++) {
7363 union spoolss_DriverInfo *info = NULL;
7364 uint32_t count = 0;
7366 result = enumprinterdrivers_level_by_architecture(mem_ctx,
7367 session_info,
7368 msg_ctx,
7369 servername,
7370 archi_table[a].long_archi,
7371 level,
7372 &info,
7373 &count);
7374 if (!W_ERROR_IS_OK(result)) {
7375 continue;
7378 for (i=0; i < count; i++) {
7379 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7380 info[i], info_p, count_p);
7384 return result;
7387 return enumprinterdrivers_level_by_architecture(mem_ctx,
7388 session_info,
7389 msg_ctx,
7390 servername,
7391 architecture,
7392 level,
7393 info_p,
7394 count_p);
7397 /****************************************************************
7398 _spoolss_EnumPrinterDrivers
7399 ****************************************************************/
7401 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7402 struct spoolss_EnumPrinterDrivers *r)
7404 const char *cservername;
7405 WERROR result;
7407 /* that's an [in out] buffer */
7409 if (!r->in.buffer && (r->in.offered != 0)) {
7410 return WERR_INVALID_PARAM;
7413 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7415 *r->out.needed = 0;
7416 *r->out.count = 0;
7417 *r->out.info = NULL;
7419 cservername = canon_servername(r->in.server);
7421 if (!is_myname_or_ipaddr(cservername)) {
7422 return WERR_UNKNOWN_PRINTER_DRIVER;
7425 result = enumprinterdrivers_level(p->mem_ctx,
7426 get_session_info_system(),
7427 p->msg_ctx,
7428 cservername,
7429 r->in.environment,
7430 r->in.level,
7431 r->out.info,
7432 r->out.count);
7433 if (!W_ERROR_IS_OK(result)) {
7434 return result;
7437 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7438 spoolss_EnumPrinterDrivers,
7439 *r->out.info, r->in.level,
7440 *r->out.count);
7441 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7442 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7444 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7447 /****************************************************************
7448 _spoolss_EnumForms
7449 ****************************************************************/
7451 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7452 struct spoolss_EnumForms *r)
7454 WERROR result;
7456 *r->out.count = 0;
7457 *r->out.needed = 0;
7458 *r->out.info = NULL;
7460 /* that's an [in out] buffer */
7462 if (!r->in.buffer && (r->in.offered != 0) ) {
7463 return WERR_INVALID_PARAM;
7466 DEBUG(4,("_spoolss_EnumForms\n"));
7467 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7468 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7470 switch (r->in.level) {
7471 case 1:
7472 result = winreg_printer_enumforms1(p->mem_ctx,
7473 get_session_info_system(),
7474 p->msg_ctx,
7475 r->out.count,
7476 r->out.info);
7477 break;
7478 default:
7479 result = WERR_UNKNOWN_LEVEL;
7480 break;
7483 if (!W_ERROR_IS_OK(result)) {
7484 return result;
7487 if (*r->out.count == 0) {
7488 return WERR_NO_MORE_ITEMS;
7491 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7492 spoolss_EnumForms,
7493 *r->out.info, r->in.level,
7494 *r->out.count);
7495 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7496 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7498 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7501 /****************************************************************
7502 _spoolss_GetForm
7503 ****************************************************************/
7505 WERROR _spoolss_GetForm(struct pipes_struct *p,
7506 struct spoolss_GetForm *r)
7508 WERROR result;
7510 /* that's an [in out] buffer */
7512 if (!r->in.buffer && (r->in.offered != 0)) {
7513 return WERR_INVALID_PARAM;
7516 DEBUG(4,("_spoolss_GetForm\n"));
7517 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7518 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7520 switch (r->in.level) {
7521 case 1:
7522 result = winreg_printer_getform1(p->mem_ctx,
7523 get_session_info_system(),
7524 p->msg_ctx,
7525 r->in.form_name,
7526 &r->out.info->info1);
7527 break;
7528 default:
7529 result = WERR_UNKNOWN_LEVEL;
7530 break;
7533 if (!W_ERROR_IS_OK(result)) {
7534 TALLOC_FREE(r->out.info);
7535 return result;
7538 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
7539 r->out.info, r->in.level);
7540 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7542 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7545 /****************************************************************************
7546 ****************************************************************************/
7548 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7549 struct spoolss_PortInfo1 *r,
7550 const char *name)
7552 r->port_name = talloc_strdup(mem_ctx, name);
7553 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7555 return WERR_OK;
7558 /****************************************************************************
7559 TODO: This probably needs distinguish between TCP/IP and Local ports
7560 somehow.
7561 ****************************************************************************/
7563 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7564 struct spoolss_PortInfo2 *r,
7565 const char *name)
7567 r->port_name = talloc_strdup(mem_ctx, name);
7568 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7570 r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7571 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7573 r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7574 W_ERROR_HAVE_NO_MEMORY(r->description);
7576 r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7577 r->reserved = 0;
7579 return WERR_OK;
7583 /****************************************************************************
7584 wrapper around the enumer ports command
7585 ****************************************************************************/
7587 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7589 char *cmd = lp_enumports_cmd();
7590 char **qlines = NULL;
7591 char *command = NULL;
7592 int numlines;
7593 int ret;
7594 int fd;
7596 *count = 0;
7597 *lines = NULL;
7599 /* if no hook then just fill in the default port */
7601 if ( !*cmd ) {
7602 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7603 return WERR_NOMEM;
7605 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7606 TALLOC_FREE(qlines);
7607 return WERR_NOMEM;
7609 qlines[1] = NULL;
7610 numlines = 1;
7612 else {
7613 /* we have a valid enumport command */
7615 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7616 if (!command) {
7617 return WERR_NOMEM;
7620 DEBUG(10,("Running [%s]\n", command));
7621 ret = smbrun(command, &fd);
7622 DEBUG(10,("Returned [%d]\n", ret));
7623 TALLOC_FREE(command);
7624 if (ret != 0) {
7625 if (fd != -1) {
7626 close(fd);
7628 return WERR_ACCESS_DENIED;
7631 numlines = 0;
7632 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7633 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7634 close(fd);
7637 *count = numlines;
7638 *lines = qlines;
7640 return WERR_OK;
7643 /****************************************************************************
7644 enumports level 1.
7645 ****************************************************************************/
7647 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7648 union spoolss_PortInfo **info_p,
7649 uint32_t *count)
7651 union spoolss_PortInfo *info = NULL;
7652 int i=0;
7653 WERROR result = WERR_OK;
7654 char **qlines = NULL;
7655 int numlines = 0;
7657 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7658 if (!W_ERROR_IS_OK(result)) {
7659 goto out;
7662 if (numlines) {
7663 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7664 if (!info) {
7665 DEBUG(10,("Returning WERR_NOMEM\n"));
7666 result = WERR_NOMEM;
7667 goto out;
7670 for (i=0; i<numlines; i++) {
7671 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7672 result = fill_port_1(info, &info[i].info1, qlines[i]);
7673 if (!W_ERROR_IS_OK(result)) {
7674 goto out;
7678 TALLOC_FREE(qlines);
7680 out:
7681 if (!W_ERROR_IS_OK(result)) {
7682 TALLOC_FREE(info);
7683 TALLOC_FREE(qlines);
7684 *count = 0;
7685 *info_p = NULL;
7686 return result;
7689 *info_p = info;
7690 *count = numlines;
7692 return WERR_OK;
7695 /****************************************************************************
7696 enumports level 2.
7697 ****************************************************************************/
7699 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7700 union spoolss_PortInfo **info_p,
7701 uint32_t *count)
7703 union spoolss_PortInfo *info = NULL;
7704 int i=0;
7705 WERROR result = WERR_OK;
7706 char **qlines = NULL;
7707 int numlines = 0;
7709 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7710 if (!W_ERROR_IS_OK(result)) {
7711 goto out;
7714 if (numlines) {
7715 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7716 if (!info) {
7717 DEBUG(10,("Returning WERR_NOMEM\n"));
7718 result = WERR_NOMEM;
7719 goto out;
7722 for (i=0; i<numlines; i++) {
7723 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7724 result = fill_port_2(info, &info[i].info2, qlines[i]);
7725 if (!W_ERROR_IS_OK(result)) {
7726 goto out;
7730 TALLOC_FREE(qlines);
7732 out:
7733 if (!W_ERROR_IS_OK(result)) {
7734 TALLOC_FREE(info);
7735 TALLOC_FREE(qlines);
7736 *count = 0;
7737 *info_p = NULL;
7738 return result;
7741 *info_p = info;
7742 *count = numlines;
7744 return WERR_OK;
7747 /****************************************************************
7748 _spoolss_EnumPorts
7749 ****************************************************************/
7751 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
7752 struct spoolss_EnumPorts *r)
7754 WERROR result;
7756 /* that's an [in out] buffer */
7758 if (!r->in.buffer && (r->in.offered != 0)) {
7759 return WERR_INVALID_PARAM;
7762 DEBUG(4,("_spoolss_EnumPorts\n"));
7764 *r->out.count = 0;
7765 *r->out.needed = 0;
7766 *r->out.info = NULL;
7768 switch (r->in.level) {
7769 case 1:
7770 result = enumports_level_1(p->mem_ctx, r->out.info,
7771 r->out.count);
7772 break;
7773 case 2:
7774 result = enumports_level_2(p->mem_ctx, r->out.info,
7775 r->out.count);
7776 break;
7777 default:
7778 return WERR_UNKNOWN_LEVEL;
7781 if (!W_ERROR_IS_OK(result)) {
7782 return result;
7785 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7786 spoolss_EnumPorts,
7787 *r->out.info, r->in.level,
7788 *r->out.count);
7789 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7790 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7792 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7795 /****************************************************************************
7796 ****************************************************************************/
7798 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
7799 const char *server,
7800 struct spoolss_SetPrinterInfoCtr *info_ctr,
7801 struct spoolss_DeviceMode *devmode,
7802 struct security_descriptor *secdesc,
7803 struct spoolss_UserLevelCtr *user_ctr,
7804 struct policy_handle *handle)
7806 struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
7807 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
7808 int snum;
7809 WERROR err = WERR_OK;
7811 /* samba does not have a concept of local, non-shared printers yet, so
7812 * make sure we always setup sharename - gd */
7813 if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
7814 (info2->printername != NULL && info2->printername[0] != '\0')) {
7815 DEBUG(5, ("spoolss_addprinterex_level_2: "
7816 "no sharename has been set, setting printername %s as sharename\n",
7817 info2->printername));
7818 info2->sharename = info2->printername;
7821 /* check to see if the printer already exists */
7822 if ((snum = print_queue_snum(info2->sharename)) != -1) {
7823 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7824 info2->sharename));
7825 return WERR_PRINTER_ALREADY_EXISTS;
7828 if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7829 if ((snum = print_queue_snum(info2->printername)) != -1) {
7830 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7831 info2->printername));
7832 return WERR_PRINTER_ALREADY_EXISTS;
7836 /* validate printer info struct */
7837 if (!info2->printername || strlen(info2->printername) == 0) {
7838 return WERR_INVALID_PRINTER_NAME;
7840 if (!info2->portname || strlen(info2->portname) == 0) {
7841 return WERR_UNKNOWN_PORT;
7843 if (!info2->drivername || strlen(info2->drivername) == 0) {
7844 return WERR_UNKNOWN_PRINTER_DRIVER;
7846 if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
7847 return WERR_UNKNOWN_PRINTPROCESSOR;
7850 /* FIXME!!! smbd should check to see if the driver is installed before
7851 trying to add a printer like this --jerry */
7853 if (*lp_addprinter_cmd() ) {
7854 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
7855 info2, p->client_id->addr,
7856 p->msg_ctx) ) {
7857 return WERR_ACCESS_DENIED;
7859 } else {
7860 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
7861 "smb.conf parameter \"addprinter command\" is defined. This "
7862 "parameter must exist for this call to succeed\n",
7863 info2->sharename ));
7866 if ((snum = print_queue_snum(info2->sharename)) == -1) {
7867 return WERR_ACCESS_DENIED;
7870 /* you must be a printer admin to add a new printer */
7871 if (!print_access_check(p->session_info,
7872 p->msg_ctx,
7873 snum,
7874 PRINTER_ACCESS_ADMINISTER)) {
7875 return WERR_ACCESS_DENIED;
7879 * Do sanity check on the requested changes for Samba.
7882 if (!check_printer_ok(p->mem_ctx, info2, snum)) {
7883 return WERR_INVALID_PARAM;
7886 if (devmode == NULL) {
7887 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
7890 update_dsspooler(p->mem_ctx,
7891 get_session_info_system(),
7892 p->msg_ctx,
7894 info2,
7895 NULL);
7897 err = winreg_update_printer(p->mem_ctx,
7898 get_session_info_system(),
7899 p->msg_ctx,
7900 info2->sharename,
7901 info2_mask,
7902 info2,
7903 devmode,
7904 secdesc);
7905 if (!W_ERROR_IS_OK(err)) {
7906 return err;
7909 err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
7910 if (!W_ERROR_IS_OK(err)) {
7911 /* Handle open failed - remove addition. */
7912 ZERO_STRUCTP(handle);
7913 return err;
7916 return WERR_OK;
7919 /****************************************************************
7920 _spoolss_AddPrinterEx
7921 ****************************************************************/
7923 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
7924 struct spoolss_AddPrinterEx *r)
7926 switch (r->in.info_ctr->level) {
7927 case 1:
7928 /* we don't handle yet */
7929 /* but I know what to do ... */
7930 return WERR_UNKNOWN_LEVEL;
7931 case 2:
7932 return spoolss_addprinterex_level_2(p, r->in.server,
7933 r->in.info_ctr,
7934 r->in.devmode_ctr->devmode,
7935 r->in.secdesc_ctr->sd,
7936 r->in.userlevel_ctr,
7937 r->out.handle);
7938 default:
7939 return WERR_UNKNOWN_LEVEL;
7943 /****************************************************************
7944 _spoolss_AddPrinter
7945 ****************************************************************/
7947 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
7948 struct spoolss_AddPrinter *r)
7950 struct spoolss_AddPrinterEx a;
7951 struct spoolss_UserLevelCtr userlevel_ctr;
7953 ZERO_STRUCT(userlevel_ctr);
7955 userlevel_ctr.level = 1;
7957 a.in.server = r->in.server;
7958 a.in.info_ctr = r->in.info_ctr;
7959 a.in.devmode_ctr = r->in.devmode_ctr;
7960 a.in.secdesc_ctr = r->in.secdesc_ctr;
7961 a.in.userlevel_ctr = &userlevel_ctr;
7962 a.out.handle = r->out.handle;
7964 return _spoolss_AddPrinterEx(p, &a);
7967 /****************************************************************
7968 _spoolss_AddPrinterDriverEx
7969 ****************************************************************/
7971 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
7972 struct spoolss_AddPrinterDriverEx *r)
7974 WERROR err = WERR_OK;
7975 const char *driver_name = NULL;
7976 uint32_t version;
7977 const char *fn;
7979 switch (p->opnum) {
7980 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7981 fn = "_spoolss_AddPrinterDriver";
7982 break;
7983 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7984 fn = "_spoolss_AddPrinterDriverEx";
7985 break;
7986 default:
7987 return WERR_INVALID_PARAM;
7991 * we only support the semantics of AddPrinterDriver()
7992 * i.e. only copy files that are newer than existing ones
7995 if (r->in.flags == 0) {
7996 return WERR_INVALID_PARAM;
7999 if (r->in.flags != APD_COPY_NEW_FILES) {
8000 return WERR_ACCESS_DENIED;
8003 /* FIXME */
8004 if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
8005 /* Clever hack from Martin Zielinski <mz@seh.de>
8006 * to allow downgrade from level 8 (Vista).
8008 DEBUG(0,("%s: level %d not yet implemented\n", fn,
8009 r->in.info_ctr->level));
8010 return WERR_UNKNOWN_LEVEL;
8013 DEBUG(5,("Cleaning driver's information\n"));
8014 err = clean_up_driver_struct(p->mem_ctx, p, r->in.info_ctr);
8015 if (!W_ERROR_IS_OK(err))
8016 goto done;
8018 DEBUG(5,("Moving driver to final destination\n"));
8019 err = move_driver_to_download_area(p, r->in.info_ctr);
8020 if (!W_ERROR_IS_OK(err)) {
8021 goto done;
8024 err = winreg_add_driver(p->mem_ctx,
8025 get_session_info_system(),
8026 p->msg_ctx,
8027 r->in.info_ctr,
8028 &driver_name,
8029 &version);
8030 if (!W_ERROR_IS_OK(err)) {
8031 goto done;
8035 * I think this is where he DrvUpgradePrinter() hook would be
8036 * be called in a driver's interface DLL on a Windows NT 4.0/2k
8037 * server. Right now, we just need to send ourselves a message
8038 * to update each printer bound to this driver. --jerry
8041 if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8042 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8043 fn, driver_name));
8046 done:
8047 return err;
8050 /****************************************************************
8051 _spoolss_AddPrinterDriver
8052 ****************************************************************/
8054 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8055 struct spoolss_AddPrinterDriver *r)
8057 struct spoolss_AddPrinterDriverEx a;
8059 switch (r->in.info_ctr->level) {
8060 case 2:
8061 case 3:
8062 case 4:
8063 case 5:
8064 break;
8065 default:
8066 return WERR_UNKNOWN_LEVEL;
8069 a.in.servername = r->in.servername;
8070 a.in.info_ctr = r->in.info_ctr;
8071 a.in.flags = APD_COPY_NEW_FILES;
8073 return _spoolss_AddPrinterDriverEx(p, &a);
8076 /****************************************************************************
8077 ****************************************************************************/
8079 struct _spoolss_paths {
8080 int type;
8081 const char *share;
8082 const char *dir;
8085 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8087 static const struct _spoolss_paths spoolss_paths[]= {
8088 { SPOOLSS_DRIVER_PATH, "print$", "DRIVERS" },
8089 { SPOOLSS_PRTPROCS_PATH, "prnproc$", "PRTPROCS" }
8092 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8093 const char *servername,
8094 const char *environment,
8095 int component,
8096 char **path)
8098 const char *pservername = NULL;
8099 const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
8100 const char *short_archi;
8102 *path = NULL;
8104 /* environment may be empty */
8105 if (environment && strlen(environment)) {
8106 long_archi = environment;
8109 /* servername may be empty */
8110 if (servername && strlen(servername)) {
8111 pservername = canon_servername(servername);
8113 if (!is_myname_or_ipaddr(pservername)) {
8114 return WERR_INVALID_PARAM;
8118 if (!(short_archi = get_short_archi(long_archi))) {
8119 return WERR_INVALID_ENVIRONMENT;
8122 switch (component) {
8123 case SPOOLSS_PRTPROCS_PATH:
8124 case SPOOLSS_DRIVER_PATH:
8125 if (pservername) {
8126 *path = talloc_asprintf(mem_ctx,
8127 "\\\\%s\\%s\\%s",
8128 pservername,
8129 spoolss_paths[component].share,
8130 short_archi);
8131 } else {
8132 *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8133 SPOOLSS_DEFAULT_SERVER_PATH,
8134 spoolss_paths[component].dir,
8135 short_archi);
8137 break;
8138 default:
8139 return WERR_INVALID_PARAM;
8142 if (!*path) {
8143 return WERR_NOMEM;
8146 return WERR_OK;
8149 /****************************************************************************
8150 ****************************************************************************/
8152 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8153 const char *servername,
8154 const char *environment,
8155 struct spoolss_DriverDirectoryInfo1 *r)
8157 WERROR werr;
8158 char *path = NULL;
8160 werr = compose_spoolss_server_path(mem_ctx,
8161 servername,
8162 environment,
8163 SPOOLSS_DRIVER_PATH,
8164 &path);
8165 if (!W_ERROR_IS_OK(werr)) {
8166 return werr;
8169 DEBUG(4,("printer driver directory: [%s]\n", path));
8171 r->directory_name = path;
8173 return WERR_OK;
8176 /****************************************************************
8177 _spoolss_GetPrinterDriverDirectory
8178 ****************************************************************/
8180 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8181 struct spoolss_GetPrinterDriverDirectory *r)
8183 WERROR werror;
8185 /* that's an [in out] buffer */
8187 if (!r->in.buffer && (r->in.offered != 0)) {
8188 return WERR_INVALID_PARAM;
8191 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8192 r->in.level));
8194 *r->out.needed = 0;
8196 /* r->in.level is ignored */
8198 werror = getprinterdriverdir_level_1(p->mem_ctx,
8199 r->in.server,
8200 r->in.environment,
8201 &r->out.info->info1);
8202 if (!W_ERROR_IS_OK(werror)) {
8203 TALLOC_FREE(r->out.info);
8204 return werror;
8207 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8208 r->out.info, r->in.level);
8209 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8211 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8214 /****************************************************************
8215 _spoolss_EnumPrinterData
8216 ****************************************************************/
8218 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8219 struct spoolss_EnumPrinterData *r)
8221 WERROR result;
8222 struct spoolss_EnumPrinterDataEx r2;
8223 uint32_t count;
8224 struct spoolss_PrinterEnumValues *info, *val = NULL;
8225 uint32_t needed;
8227 r2.in.handle = r->in.handle;
8228 r2.in.key_name = "PrinterDriverData";
8229 r2.in.offered = 0;
8230 r2.out.count = &count;
8231 r2.out.info = &info;
8232 r2.out.needed = &needed;
8234 result = _spoolss_EnumPrinterDataEx(p, &r2);
8235 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8236 r2.in.offered = needed;
8237 result = _spoolss_EnumPrinterDataEx(p, &r2);
8239 if (!W_ERROR_IS_OK(result)) {
8240 return result;
8244 * The NT machine wants to know the biggest size of value and data
8246 * cf: MSDN EnumPrinterData remark section
8249 if (!r->in.value_offered && !r->in.data_offered) {
8250 uint32_t biggest_valuesize = 0;
8251 uint32_t biggest_datasize = 0;
8252 int i, name_length;
8254 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8256 for (i=0; i<count; i++) {
8258 name_length = strlen(info[i].value_name);
8259 if (strlen(info[i].value_name) > biggest_valuesize) {
8260 biggest_valuesize = name_length;
8263 if (info[i].data_length > biggest_datasize) {
8264 biggest_datasize = info[i].data_length;
8267 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8268 biggest_datasize));
8271 /* the value is an UNICODE string but real_value_size is the length
8272 in bytes including the trailing 0 */
8274 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8275 *r->out.data_needed = biggest_datasize;
8277 DEBUG(6,("final values: [%d], [%d]\n",
8278 *r->out.value_needed, *r->out.data_needed));
8280 return WERR_OK;
8283 if (r->in.enum_index < count) {
8284 val = &info[r->in.enum_index];
8287 if (val == NULL) {
8288 /* out_value should default to "" or else NT4 has
8289 problems unmarshalling the response */
8291 if (r->in.value_offered) {
8292 *r->out.value_needed = 1;
8293 r->out.value_name = talloc_strdup(r, "");
8294 if (!r->out.value_name) {
8295 return WERR_NOMEM;
8297 } else {
8298 r->out.value_name = NULL;
8299 *r->out.value_needed = 0;
8302 /* the data is counted in bytes */
8304 *r->out.data_needed = r->in.data_offered;
8306 result = WERR_NO_MORE_ITEMS;
8307 } else {
8309 * the value is:
8310 * - counted in bytes in the request
8311 * - counted in UNICODE chars in the max reply
8312 * - counted in bytes in the real size
8314 * take a pause *before* coding not *during* coding
8317 /* name */
8318 if (r->in.value_offered) {
8319 r->out.value_name = talloc_strdup(r, val->value_name);
8320 if (!r->out.value_name) {
8321 return WERR_NOMEM;
8323 *r->out.value_needed = val->value_name_len;
8324 } else {
8325 r->out.value_name = NULL;
8326 *r->out.value_needed = 0;
8329 /* type */
8331 *r->out.type = val->type;
8333 /* data - counted in bytes */
8336 * See the section "Dynamically Typed Query Parameters"
8337 * in MS-RPRN.
8340 if (r->out.data && val->data && val->data->data &&
8341 val->data_length && r->in.data_offered) {
8342 memcpy(r->out.data, val->data->data,
8343 MIN(val->data_length,r->in.data_offered));
8346 *r->out.data_needed = val->data_length;
8348 result = WERR_OK;
8351 return result;
8354 /****************************************************************
8355 _spoolss_SetPrinterData
8356 ****************************************************************/
8358 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8359 struct spoolss_SetPrinterData *r)
8361 struct spoolss_SetPrinterDataEx r2;
8363 r2.in.handle = r->in.handle;
8364 r2.in.key_name = "PrinterDriverData";
8365 r2.in.value_name = r->in.value_name;
8366 r2.in.type = r->in.type;
8367 r2.in.data = r->in.data;
8368 r2.in.offered = r->in.offered;
8370 return _spoolss_SetPrinterDataEx(p, &r2);
8373 /****************************************************************
8374 _spoolss_ResetPrinter
8375 ****************************************************************/
8377 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8378 struct spoolss_ResetPrinter *r)
8380 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8381 int snum;
8383 DEBUG(5,("_spoolss_ResetPrinter\n"));
8386 * All we do is to check to see if the handle and queue is valid.
8387 * This call really doesn't mean anything to us because we only
8388 * support RAW printing. --jerry
8391 if (!Printer) {
8392 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8393 OUR_HANDLE(r->in.handle)));
8394 return WERR_BADFID;
8397 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8398 return WERR_BADFID;
8401 /* blindly return success */
8402 return WERR_OK;
8405 /****************************************************************
8406 _spoolss_DeletePrinterData
8407 ****************************************************************/
8409 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8410 struct spoolss_DeletePrinterData *r)
8412 struct spoolss_DeletePrinterDataEx r2;
8414 r2.in.handle = r->in.handle;
8415 r2.in.key_name = "PrinterDriverData";
8416 r2.in.value_name = r->in.value_name;
8418 return _spoolss_DeletePrinterDataEx(p, &r2);
8421 /****************************************************************
8422 _spoolss_AddForm
8423 ****************************************************************/
8425 WERROR _spoolss_AddForm(struct pipes_struct *p,
8426 struct spoolss_AddForm *r)
8428 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8429 int snum = -1;
8430 WERROR status = WERR_OK;
8432 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8434 DEBUG(5,("_spoolss_AddForm\n"));
8436 if (!Printer) {
8437 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8438 OUR_HANDLE(r->in.handle)));
8439 return WERR_BADFID;
8442 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8443 and not a printer admin, then fail */
8445 if ((p->session_info->utok.uid != sec_initial_uid()) &&
8446 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8447 !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8448 p->session_info->info3->base.domain.string,
8449 NULL,
8450 p->session_info->security_token,
8451 lp_printer_admin(snum))) {
8452 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8453 return WERR_ACCESS_DENIED;
8456 switch (form->flags) {
8457 case SPOOLSS_FORM_USER:
8458 case SPOOLSS_FORM_BUILTIN:
8459 case SPOOLSS_FORM_PRINTER:
8460 break;
8461 default:
8462 return WERR_INVALID_PARAM;
8465 status = winreg_printer_addform1(p->mem_ctx,
8466 get_session_info_system(),
8467 p->msg_ctx,
8468 form);
8469 if (!W_ERROR_IS_OK(status)) {
8470 return status;
8474 * ChangeID must always be set if this is a printer
8476 if (Printer->printer_type == SPLHND_PRINTER) {
8477 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8478 return WERR_BADFID;
8481 status = winreg_printer_update_changeid(p->mem_ctx,
8482 get_session_info_system(),
8483 p->msg_ctx,
8484 lp_const_servicename(snum));
8485 if (!W_ERROR_IS_OK(status)) {
8486 return status;
8490 return status;
8493 /****************************************************************
8494 _spoolss_DeleteForm
8495 ****************************************************************/
8497 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8498 struct spoolss_DeleteForm *r)
8500 const char *form_name = r->in.form_name;
8501 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8502 int snum = -1;
8503 WERROR status = WERR_OK;
8505 DEBUG(5,("_spoolss_DeleteForm\n"));
8507 if (!Printer) {
8508 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8509 OUR_HANDLE(r->in.handle)));
8510 return WERR_BADFID;
8513 if ((p->session_info->utok.uid != sec_initial_uid()) &&
8514 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8515 !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8516 p->session_info->info3->base.domain.string,
8517 NULL,
8518 p->session_info->security_token,
8519 lp_printer_admin(snum))) {
8520 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8521 return WERR_ACCESS_DENIED;
8524 status = winreg_printer_deleteform1(p->mem_ctx,
8525 get_session_info_system(),
8526 p->msg_ctx,
8527 form_name);
8528 if (!W_ERROR_IS_OK(status)) {
8529 return status;
8533 * ChangeID must always be set if this is a printer
8535 if (Printer->printer_type == SPLHND_PRINTER) {
8536 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8537 return WERR_BADFID;
8540 status = winreg_printer_update_changeid(p->mem_ctx,
8541 get_session_info_system(),
8542 p->msg_ctx,
8543 lp_const_servicename(snum));
8544 if (!W_ERROR_IS_OK(status)) {
8545 return status;
8549 return status;
8552 /****************************************************************
8553 _spoolss_SetForm
8554 ****************************************************************/
8556 WERROR _spoolss_SetForm(struct pipes_struct *p,
8557 struct spoolss_SetForm *r)
8559 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8560 const char *form_name = r->in.form_name;
8561 int snum = -1;
8562 WERROR status = WERR_OK;
8564 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8566 DEBUG(5,("_spoolss_SetForm\n"));
8568 if (!Printer) {
8569 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8570 OUR_HANDLE(r->in.handle)));
8571 return WERR_BADFID;
8574 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8575 and not a printer admin, then fail */
8577 if ((p->session_info->utok.uid != sec_initial_uid()) &&
8578 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8579 !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8580 p->session_info->info3->base.domain.string,
8581 NULL,
8582 p->session_info->security_token,
8583 lp_printer_admin(snum))) {
8584 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8585 return WERR_ACCESS_DENIED;
8588 status = winreg_printer_setform1(p->mem_ctx,
8589 get_session_info_system(),
8590 p->msg_ctx,
8591 form_name,
8592 form);
8593 if (!W_ERROR_IS_OK(status)) {
8594 return status;
8598 * ChangeID must always be set if this is a printer
8600 if (Printer->printer_type == SPLHND_PRINTER) {
8601 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8602 return WERR_BADFID;
8605 status = winreg_printer_update_changeid(p->mem_ctx,
8606 get_session_info_system(),
8607 p->msg_ctx,
8608 lp_const_servicename(snum));
8609 if (!W_ERROR_IS_OK(status)) {
8610 return status;
8614 return status;
8617 /****************************************************************************
8618 fill_print_processor1
8619 ****************************************************************************/
8621 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8622 struct spoolss_PrintProcessorInfo1 *r,
8623 const char *print_processor_name)
8625 r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8626 W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8628 return WERR_OK;
8631 /****************************************************************************
8632 enumprintprocessors level 1.
8633 ****************************************************************************/
8635 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8636 union spoolss_PrintProcessorInfo **info_p,
8637 uint32_t *count)
8639 union spoolss_PrintProcessorInfo *info;
8640 WERROR result;
8642 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8643 W_ERROR_HAVE_NO_MEMORY(info);
8645 *count = 1;
8647 result = fill_print_processor1(info, &info[0].info1, "winprint");
8648 if (!W_ERROR_IS_OK(result)) {
8649 goto out;
8652 out:
8653 if (!W_ERROR_IS_OK(result)) {
8654 TALLOC_FREE(info);
8655 *count = 0;
8656 return result;
8659 *info_p = info;
8661 return WERR_OK;
8664 /****************************************************************
8665 _spoolss_EnumPrintProcessors
8666 ****************************************************************/
8668 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
8669 struct spoolss_EnumPrintProcessors *r)
8671 WERROR result;
8673 /* that's an [in out] buffer */
8675 if (!r->in.buffer && (r->in.offered != 0)) {
8676 return WERR_INVALID_PARAM;
8679 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8682 * Enumerate the print processors ...
8684 * Just reply with "winprint", to keep NT happy
8685 * and I can use my nice printer checker.
8688 *r->out.count = 0;
8689 *r->out.needed = 0;
8690 *r->out.info = NULL;
8692 if (!get_short_archi(r->in.environment)) {
8693 return WERR_INVALID_ENVIRONMENT;
8696 switch (r->in.level) {
8697 case 1:
8698 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8699 r->out.count);
8700 break;
8701 default:
8702 return WERR_UNKNOWN_LEVEL;
8705 if (!W_ERROR_IS_OK(result)) {
8706 return result;
8709 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8710 spoolss_EnumPrintProcessors,
8711 *r->out.info, r->in.level,
8712 *r->out.count);
8713 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8714 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8716 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8719 /****************************************************************************
8720 fill_printprocdatatype1
8721 ****************************************************************************/
8723 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8724 struct spoolss_PrintProcDataTypesInfo1 *r,
8725 const char *name_array)
8727 r->name_array = talloc_strdup(mem_ctx, name_array);
8728 W_ERROR_HAVE_NO_MEMORY(r->name_array);
8730 return WERR_OK;
8733 /****************************************************************************
8734 enumprintprocdatatypes level 1.
8735 ****************************************************************************/
8737 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8738 union spoolss_PrintProcDataTypesInfo **info_p,
8739 uint32_t *count)
8741 WERROR result;
8742 union spoolss_PrintProcDataTypesInfo *info;
8744 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8745 W_ERROR_HAVE_NO_MEMORY(info);
8747 *count = 1;
8749 result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8750 if (!W_ERROR_IS_OK(result)) {
8751 goto out;
8754 out:
8755 if (!W_ERROR_IS_OK(result)) {
8756 TALLOC_FREE(info);
8757 *count = 0;
8758 return result;
8761 *info_p = info;
8763 return WERR_OK;
8766 /****************************************************************
8767 _spoolss_EnumPrintProcDataTypes
8768 ****************************************************************/
8770 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
8771 struct spoolss_EnumPrintProcDataTypes *r)
8773 WERROR result;
8775 /* that's an [in out] buffer */
8777 if (!r->in.buffer && (r->in.offered != 0)) {
8778 return WERR_INVALID_PARAM;
8781 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8783 *r->out.count = 0;
8784 *r->out.needed = 0;
8785 *r->out.info = NULL;
8787 if (r->in.print_processor_name == NULL ||
8788 !strequal(r->in.print_processor_name, "winprint")) {
8789 return WERR_UNKNOWN_PRINTPROCESSOR;
8792 switch (r->in.level) {
8793 case 1:
8794 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8795 r->out.count);
8796 break;
8797 default:
8798 return WERR_UNKNOWN_LEVEL;
8801 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8802 spoolss_EnumPrintProcDataTypes,
8803 *r->out.info, r->in.level,
8804 *r->out.count);
8805 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8806 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8808 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8811 /****************************************************************************
8812 fill_monitor_1
8813 ****************************************************************************/
8815 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8816 struct spoolss_MonitorInfo1 *r,
8817 const char *monitor_name)
8819 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8820 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8822 return WERR_OK;
8825 /****************************************************************************
8826 fill_monitor_2
8827 ****************************************************************************/
8829 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8830 struct spoolss_MonitorInfo2 *r,
8831 const char *monitor_name,
8832 const char *environment,
8833 const char *dll_name)
8835 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8836 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8837 r->environment = talloc_strdup(mem_ctx, environment);
8838 W_ERROR_HAVE_NO_MEMORY(r->environment);
8839 r->dll_name = talloc_strdup(mem_ctx, dll_name);
8840 W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8842 return WERR_OK;
8845 /****************************************************************************
8846 enumprintmonitors level 1.
8847 ****************************************************************************/
8849 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8850 union spoolss_MonitorInfo **info_p,
8851 uint32_t *count)
8853 union spoolss_MonitorInfo *info;
8854 WERROR result = WERR_OK;
8856 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8857 W_ERROR_HAVE_NO_MEMORY(info);
8859 *count = 2;
8861 result = fill_monitor_1(info, &info[0].info1,
8862 SPL_LOCAL_PORT);
8863 if (!W_ERROR_IS_OK(result)) {
8864 goto out;
8867 result = fill_monitor_1(info, &info[1].info1,
8868 SPL_TCPIP_PORT);
8869 if (!W_ERROR_IS_OK(result)) {
8870 goto out;
8873 out:
8874 if (!W_ERROR_IS_OK(result)) {
8875 TALLOC_FREE(info);
8876 *count = 0;
8877 return result;
8880 *info_p = info;
8882 return WERR_OK;
8885 /****************************************************************************
8886 enumprintmonitors level 2.
8887 ****************************************************************************/
8889 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8890 union spoolss_MonitorInfo **info_p,
8891 uint32_t *count)
8893 union spoolss_MonitorInfo *info;
8894 WERROR result = WERR_OK;
8896 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8897 W_ERROR_HAVE_NO_MEMORY(info);
8899 *count = 2;
8901 result = fill_monitor_2(info, &info[0].info2,
8902 SPL_LOCAL_PORT,
8903 "Windows NT X86", /* FIXME */
8904 "localmon.dll");
8905 if (!W_ERROR_IS_OK(result)) {
8906 goto out;
8909 result = fill_monitor_2(info, &info[1].info2,
8910 SPL_TCPIP_PORT,
8911 "Windows NT X86", /* FIXME */
8912 "tcpmon.dll");
8913 if (!W_ERROR_IS_OK(result)) {
8914 goto out;
8917 out:
8918 if (!W_ERROR_IS_OK(result)) {
8919 TALLOC_FREE(info);
8920 *count = 0;
8921 return result;
8924 *info_p = info;
8926 return WERR_OK;
8929 /****************************************************************
8930 _spoolss_EnumMonitors
8931 ****************************************************************/
8933 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
8934 struct spoolss_EnumMonitors *r)
8936 WERROR result;
8938 /* that's an [in out] buffer */
8940 if (!r->in.buffer && (r->in.offered != 0)) {
8941 return WERR_INVALID_PARAM;
8944 DEBUG(5,("_spoolss_EnumMonitors\n"));
8947 * Enumerate the print monitors ...
8949 * Just reply with "Local Port", to keep NT happy
8950 * and I can use my nice printer checker.
8953 *r->out.count = 0;
8954 *r->out.needed = 0;
8955 *r->out.info = NULL;
8957 switch (r->in.level) {
8958 case 1:
8959 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8960 r->out.count);
8961 break;
8962 case 2:
8963 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8964 r->out.count);
8965 break;
8966 default:
8967 return WERR_UNKNOWN_LEVEL;
8970 if (!W_ERROR_IS_OK(result)) {
8971 return result;
8974 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8975 spoolss_EnumMonitors,
8976 *r->out.info, r->in.level,
8977 *r->out.count);
8978 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8979 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8981 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8984 /****************************************************************************
8985 ****************************************************************************/
8987 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8988 const print_queue_struct *queue,
8989 int count, int snum,
8990 struct spoolss_PrinterInfo2 *pinfo2,
8991 uint32_t jobid,
8992 struct spoolss_JobInfo1 *r)
8994 int i = 0;
8995 bool found = false;
8997 for (i=0; i<count; i++) {
8998 if (queue[i].job == (int)jobid) {
8999 found = true;
9000 break;
9004 if (found == false) {
9005 /* NT treats not found as bad param... yet another bad choice */
9006 return WERR_INVALID_PARAM;
9009 return fill_job_info1(mem_ctx,
9011 &queue[i],
9013 snum,
9014 pinfo2);
9017 /****************************************************************************
9018 ****************************************************************************/
9020 static WERROR getjob_level_2(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_JobInfo2 *r)
9027 int i = 0;
9028 bool found = false;
9029 struct spoolss_DeviceMode *devmode;
9030 WERROR result;
9032 for (i=0; i<count; i++) {
9033 if (queue[i].job == (int)jobid) {
9034 found = true;
9035 break;
9039 if (found == false) {
9040 /* NT treats not found as bad param... yet another bad
9041 choice */
9042 return WERR_INVALID_PARAM;
9046 * if the print job does not have a DEVMODE associated with it,
9047 * just use the one for the printer. A NULL devicemode is not
9048 * a failure condition
9051 devmode = print_job_devmode(lp_const_servicename(snum), jobid);
9052 if (!devmode) {
9053 result = spoolss_create_default_devmode(mem_ctx,
9054 pinfo2->printername,
9055 &devmode);
9056 if (!W_ERROR_IS_OK(result)) {
9057 DEBUG(3, ("Can't proceed w/o a devmode!"));
9058 return result;
9062 return fill_job_info2(mem_ctx,
9064 &queue[i],
9066 snum,
9067 pinfo2,
9068 devmode);
9071 /****************************************************************
9072 _spoolss_GetJob
9073 ****************************************************************/
9075 WERROR _spoolss_GetJob(struct pipes_struct *p,
9076 struct spoolss_GetJob *r)
9078 WERROR result = WERR_OK;
9079 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9080 int snum;
9081 int count;
9082 print_queue_struct *queue = NULL;
9083 print_status_struct prt_status;
9085 /* that's an [in out] buffer */
9087 if (!r->in.buffer && (r->in.offered != 0)) {
9088 return WERR_INVALID_PARAM;
9091 DEBUG(5,("_spoolss_GetJob\n"));
9093 *r->out.needed = 0;
9095 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9096 return WERR_BADFID;
9099 result = winreg_get_printer(p->mem_ctx,
9100 get_session_info_system(),
9101 p->msg_ctx,
9102 lp_const_servicename(snum),
9103 &pinfo2);
9104 if (!W_ERROR_IS_OK(result)) {
9105 return result;
9108 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9110 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9111 count, prt_status.status, prt_status.message));
9113 switch (r->in.level) {
9114 case 1:
9115 result = getjob_level_1(p->mem_ctx,
9116 queue, count, snum, pinfo2,
9117 r->in.job_id, &r->out.info->info1);
9118 break;
9119 case 2:
9120 result = getjob_level_2(p->mem_ctx,
9121 queue, count, snum, pinfo2,
9122 r->in.job_id, &r->out.info->info2);
9123 break;
9124 default:
9125 result = WERR_UNKNOWN_LEVEL;
9126 break;
9129 SAFE_FREE(queue);
9130 TALLOC_FREE(pinfo2);
9132 if (!W_ERROR_IS_OK(result)) {
9133 TALLOC_FREE(r->out.info);
9134 return result;
9137 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9138 r->in.level);
9139 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9141 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9144 /****************************************************************
9145 _spoolss_GetPrinterDataEx
9146 ****************************************************************/
9148 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9149 struct spoolss_GetPrinterDataEx *r)
9152 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9153 const char *printer;
9154 int snum = 0;
9155 WERROR result = WERR_OK;
9156 DATA_BLOB blob;
9157 enum winreg_Type val_type;
9158 uint8_t *val_data;
9159 uint32_t val_size;
9162 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9164 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9165 r->in.key_name, r->in.value_name));
9167 /* in case of problem, return some default values */
9169 *r->out.needed = 0;
9170 *r->out.type = REG_NONE;
9172 if (!Printer) {
9173 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9174 OUR_HANDLE(r->in.handle)));
9175 result = WERR_BADFID;
9176 goto done;
9179 /* Is the handle to a printer or to the server? */
9181 if (Printer->printer_type == SPLHND_SERVER) {
9183 union spoolss_PrinterData data;
9185 result = getprinterdata_printer_server(p->mem_ctx,
9186 r->in.value_name,
9187 r->out.type,
9188 &data);
9189 if (!W_ERROR_IS_OK(result)) {
9190 return result;
9193 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
9194 *r->out.type, &data);
9195 if (!W_ERROR_IS_OK(result)) {
9196 return result;
9199 *r->out.needed = blob.length;
9201 if (r->in.offered >= *r->out.needed) {
9202 memcpy(r->out.data, blob.data, blob.length);
9205 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9208 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9209 return WERR_BADFID;
9211 printer = lp_const_servicename(snum);
9213 /* check to see if the keyname is valid */
9214 if (!strlen(r->in.key_name)) {
9215 return WERR_INVALID_PARAM;
9218 /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9219 if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9220 strequal(r->in.value_name, "ChangeId")) {
9221 *r->out.type = REG_DWORD;
9222 *r->out.needed = 4;
9223 if (r->in.offered >= *r->out.needed) {
9224 uint32_t changeid = 0;
9226 result = winreg_printer_get_changeid(p->mem_ctx,
9227 get_session_info_system(),
9228 p->msg_ctx,
9229 printer,
9230 &changeid);
9231 if (!W_ERROR_IS_OK(result)) {
9232 return result;
9235 SIVAL(r->out.data, 0, changeid);
9236 result = WERR_OK;
9238 goto done;
9241 result = winreg_get_printer_dataex(p->mem_ctx,
9242 get_session_info_system(),
9243 p->msg_ctx,
9244 printer,
9245 r->in.key_name,
9246 r->in.value_name,
9247 &val_type,
9248 &val_data,
9249 &val_size);
9250 if (!W_ERROR_IS_OK(result)) {
9251 return result;
9254 *r->out.needed = val_size;
9255 *r->out.type = val_type;
9257 if (r->in.offered >= *r->out.needed) {
9258 memcpy(r->out.data, val_data, val_size);
9261 done:
9262 /* retain type when returning WERR_MORE_DATA */
9263 r->out.data = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
9265 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9268 /****************************************************************
9269 _spoolss_SetPrinterDataEx
9270 ****************************************************************/
9272 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9273 struct spoolss_SetPrinterDataEx *r)
9275 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9276 int snum = 0;
9277 WERROR result = WERR_OK;
9278 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9279 char *oid_string;
9281 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9283 /* From MSDN documentation of SetPrinterDataEx: pass request to
9284 SetPrinterData if key is "PrinterDriverData" */
9286 if (!Printer) {
9287 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9288 OUR_HANDLE(r->in.handle)));
9289 return WERR_BADFID;
9292 if (Printer->printer_type == SPLHND_SERVER) {
9293 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9294 "Not implemented for server handles yet\n"));
9295 return WERR_INVALID_PARAM;
9298 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9299 return WERR_BADFID;
9303 * Access check : NT returns "access denied" if you make a
9304 * SetPrinterData call without the necessary privildge.
9305 * we were originally returning OK if nothing changed
9306 * which made Win2k issue **a lot** of SetPrinterData
9307 * when connecting to a printer --jerry
9310 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9311 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9312 "change denied by handle access permissions\n"));
9313 return WERR_ACCESS_DENIED;
9316 result = winreg_get_printer(Printer,
9317 get_session_info_system(),
9318 p->msg_ctx,
9319 lp_servicename(snum),
9320 &pinfo2);
9321 if (!W_ERROR_IS_OK(result)) {
9322 return result;
9325 /* check for OID in valuename */
9327 oid_string = strchr(r->in.value_name, ',');
9328 if (oid_string) {
9329 *oid_string = '\0';
9330 oid_string++;
9333 /* save the registry data */
9335 result = winreg_set_printer_dataex(p->mem_ctx,
9336 get_session_info_system(),
9337 p->msg_ctx,
9338 pinfo2->sharename,
9339 r->in.key_name,
9340 r->in.value_name,
9341 r->in.type,
9342 r->in.data,
9343 r->in.offered);
9345 if (W_ERROR_IS_OK(result)) {
9346 /* save the OID if one was specified */
9347 if (oid_string) {
9348 char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9349 r->in.key_name, SPOOL_OID_KEY);
9350 if (!str) {
9351 result = WERR_NOMEM;
9352 goto done;
9356 * I'm not checking the status here on purpose. Don't know
9357 * if this is right, but I'm returning the status from the
9358 * previous set_printer_dataex() call. I have no idea if
9359 * this is right. --jerry
9361 winreg_set_printer_dataex(p->mem_ctx,
9362 get_session_info_system(),
9363 p->msg_ctx,
9364 pinfo2->sharename,
9365 str,
9366 r->in.value_name,
9367 REG_SZ,
9368 (uint8_t *) oid_string,
9369 strlen(oid_string) + 1);
9372 result = winreg_printer_update_changeid(p->mem_ctx,
9373 get_session_info_system(),
9374 p->msg_ctx,
9375 lp_const_servicename(snum));
9379 done:
9380 talloc_free(pinfo2);
9381 return result;
9384 /****************************************************************
9385 _spoolss_DeletePrinterDataEx
9386 ****************************************************************/
9388 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9389 struct spoolss_DeletePrinterDataEx *r)
9391 const char *printer;
9392 int snum=0;
9393 WERROR status = WERR_OK;
9394 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9396 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9398 if (!Printer) {
9399 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9400 "Invalid handle (%s:%u:%u).\n",
9401 OUR_HANDLE(r->in.handle)));
9402 return WERR_BADFID;
9405 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9406 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9407 "printer properties change denied by handle\n"));
9408 return WERR_ACCESS_DENIED;
9411 if (!r->in.value_name || !r->in.key_name) {
9412 return WERR_NOMEM;
9415 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9416 return WERR_BADFID;
9418 printer = lp_const_servicename(snum);
9420 status = winreg_delete_printer_dataex(p->mem_ctx,
9421 get_session_info_system(),
9422 p->msg_ctx,
9423 printer,
9424 r->in.key_name,
9425 r->in.value_name);
9426 if (W_ERROR_IS_OK(status)) {
9427 status = winreg_printer_update_changeid(p->mem_ctx,
9428 get_session_info_system(),
9429 p->msg_ctx,
9430 printer);
9433 return status;
9436 /****************************************************************
9437 _spoolss_EnumPrinterKey
9438 ****************************************************************/
9440 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9441 struct spoolss_EnumPrinterKey *r)
9443 uint32_t num_keys;
9444 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9445 int snum = 0;
9446 WERROR result = WERR_BADFILE;
9447 const char **array = NULL;
9448 DATA_BLOB blob;
9450 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9452 if (!Printer) {
9453 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9454 OUR_HANDLE(r->in.handle)));
9455 return WERR_BADFID;
9458 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9459 return WERR_BADFID;
9462 result = winreg_enum_printer_key(p->mem_ctx,
9463 get_session_info_system(),
9464 p->msg_ctx,
9465 lp_const_servicename(snum),
9466 r->in.key_name,
9467 &num_keys,
9468 &array);
9469 if (!W_ERROR_IS_OK(result)) {
9470 goto done;
9473 if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9474 result = WERR_NOMEM;
9475 goto done;
9478 *r->out._ndr_size = r->in.offered / 2;
9479 *r->out.needed = blob.length;
9481 if (r->in.offered < *r->out.needed) {
9482 result = WERR_MORE_DATA;
9483 } else {
9484 result = WERR_OK;
9485 r->out.key_buffer->string_array = array;
9488 done:
9489 if (!W_ERROR_IS_OK(result)) {
9490 TALLOC_FREE(array);
9491 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9492 *r->out.needed = 0;
9496 return result;
9499 /****************************************************************
9500 _spoolss_DeletePrinterKey
9501 ****************************************************************/
9503 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9504 struct spoolss_DeletePrinterKey *r)
9506 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9507 int snum=0;
9508 WERROR status;
9509 const char *printer;
9511 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9513 if (!Printer) {
9514 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9515 OUR_HANDLE(r->in.handle)));
9516 return WERR_BADFID;
9519 /* if keyname == NULL, return error */
9520 if ( !r->in.key_name )
9521 return WERR_INVALID_PARAM;
9523 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9524 return WERR_BADFID;
9527 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9528 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9529 "printer properties change denied by handle\n"));
9530 return WERR_ACCESS_DENIED;
9533 printer = lp_const_servicename(snum);
9535 /* delete the key and all subkeys */
9536 status = winreg_delete_printer_key(p->mem_ctx,
9537 get_session_info_system(),
9538 p->msg_ctx,
9539 printer,
9540 r->in.key_name);
9541 if (W_ERROR_IS_OK(status)) {
9542 status = winreg_printer_update_changeid(p->mem_ctx,
9543 get_session_info_system(),
9544 p->msg_ctx,
9545 printer);
9548 return status;
9551 /****************************************************************
9552 _spoolss_EnumPrinterDataEx
9553 ****************************************************************/
9555 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
9556 struct spoolss_EnumPrinterDataEx *r)
9558 uint32_t count = 0;
9559 struct spoolss_PrinterEnumValues *info = NULL;
9560 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9561 int snum;
9562 WERROR result;
9564 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9566 *r->out.count = 0;
9567 *r->out.needed = 0;
9568 *r->out.info = NULL;
9570 if (!Printer) {
9571 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9572 OUR_HANDLE(r->in.handle)));
9573 return WERR_BADFID;
9577 * first check for a keyname of NULL or "". Win2k seems to send
9578 * this a lot and we should send back WERR_INVALID_PARAM
9579 * no need to spend time looking up the printer in this case.
9580 * --jerry
9583 if (!strlen(r->in.key_name)) {
9584 result = WERR_INVALID_PARAM;
9585 goto done;
9588 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9589 return WERR_BADFID;
9592 /* now look for a match on the key name */
9593 result = winreg_enum_printer_dataex(p->mem_ctx,
9594 get_session_info_system(),
9595 p->msg_ctx,
9596 lp_const_servicename(snum),
9597 r->in.key_name,
9598 &count,
9599 &info);
9600 if (!W_ERROR_IS_OK(result)) {
9601 goto done;
9604 #if 0 /* FIXME - gd */
9605 /* housekeeping information in the reply */
9607 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9608 * the hand marshalled container size is a multiple
9609 * of 4 bytes for RPC alignment.
9612 if (needed % 4) {
9613 needed += 4-(needed % 4);
9615 #endif
9616 *r->out.count = count;
9617 *r->out.info = info;
9619 done:
9620 if (!W_ERROR_IS_OK(result)) {
9621 return result;
9624 *r->out.needed = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9625 spoolss_EnumPrinterDataEx,
9626 *r->out.info,
9627 *r->out.count);
9628 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9629 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9631 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9634 /****************************************************************************
9635 ****************************************************************************/
9637 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9638 const char *servername,
9639 const char *environment,
9640 struct spoolss_PrintProcessorDirectoryInfo1 *r)
9642 WERROR werr;
9643 char *path = NULL;
9645 werr = compose_spoolss_server_path(mem_ctx,
9646 servername,
9647 environment,
9648 SPOOLSS_PRTPROCS_PATH,
9649 &path);
9650 if (!W_ERROR_IS_OK(werr)) {
9651 return werr;
9654 DEBUG(4,("print processor directory: [%s]\n", path));
9656 r->directory_name = path;
9658 return WERR_OK;
9661 /****************************************************************
9662 _spoolss_GetPrintProcessorDirectory
9663 ****************************************************************/
9665 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
9666 struct spoolss_GetPrintProcessorDirectory *r)
9668 WERROR result;
9669 char *prnproc_share = NULL;
9670 bool prnproc_share_exists = false;
9671 int snum;
9673 /* that's an [in out] buffer */
9675 if (!r->in.buffer && (r->in.offered != 0)) {
9676 return WERR_INVALID_PARAM;
9679 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9680 r->in.level));
9682 *r->out.needed = 0;
9684 /* r->in.level is ignored */
9686 /* We always should reply with a local print processor directory so that
9687 * users are not forced to have a [prnproc$] share on the Samba spoolss
9688 * server, if users decide to do so, lets announce it though - Guenther */
9690 snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
9691 if (!prnproc_share) {
9692 return WERR_NOMEM;
9694 if (snum != -1) {
9695 prnproc_share_exists = true;
9698 result = getprintprocessordirectory_level_1(p->mem_ctx,
9699 prnproc_share_exists ? r->in.server : NULL,
9700 r->in.environment,
9701 &r->out.info->info1);
9702 if (!W_ERROR_IS_OK(result)) {
9703 TALLOC_FREE(r->out.info);
9704 return result;
9707 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
9708 r->out.info, r->in.level);
9709 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9711 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9714 /*******************************************************************
9715 ********************************************************************/
9717 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9718 const char *dllname)
9720 enum ndr_err_code ndr_err;
9721 struct spoolss_MonitorUi ui;
9723 ui.dll_name = dllname;
9725 ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
9726 (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9727 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9728 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9730 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9733 /*******************************************************************
9734 Streams the monitor UI DLL name in UNICODE
9735 *******************************************************************/
9737 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9738 struct security_token *token, DATA_BLOB *in,
9739 DATA_BLOB *out, uint32_t *needed)
9741 const char *dllname = "tcpmonui.dll";
9743 *needed = (strlen(dllname)+1) * 2;
9745 if (out->length < *needed) {
9746 return WERR_INSUFFICIENT_BUFFER;
9749 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9750 return WERR_NOMEM;
9753 return WERR_OK;
9756 /*******************************************************************
9757 ********************************************************************/
9759 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9760 struct spoolss_PortData1 *port1,
9761 const DATA_BLOB *buf)
9763 enum ndr_err_code ndr_err;
9764 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
9765 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9766 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9767 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9769 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9772 /*******************************************************************
9773 ********************************************************************/
9775 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9776 struct spoolss_PortData2 *port2,
9777 const DATA_BLOB *buf)
9779 enum ndr_err_code ndr_err;
9780 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
9781 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9782 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9783 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9785 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9788 /*******************************************************************
9789 Create a new TCP/IP port
9790 *******************************************************************/
9792 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9793 struct security_token *token, DATA_BLOB *in,
9794 DATA_BLOB *out, uint32_t *needed)
9796 struct spoolss_PortData1 port1;
9797 struct spoolss_PortData2 port2;
9798 char *device_uri = NULL;
9799 uint32_t version;
9801 const char *portname;
9802 const char *hostaddress;
9803 const char *queue;
9804 uint32_t port_number;
9805 uint32_t protocol;
9807 /* peek for spoolss_PortData version */
9809 if (!in || (in->length < (128 + 4))) {
9810 return WERR_GENERAL_FAILURE;
9813 version = IVAL(in->data, 128);
9815 switch (version) {
9816 case 1:
9817 ZERO_STRUCT(port1);
9819 if (!pull_port_data_1(mem_ctx, &port1, in)) {
9820 return WERR_NOMEM;
9823 portname = port1.portname;
9824 hostaddress = port1.hostaddress;
9825 queue = port1.queue;
9826 protocol = port1.protocol;
9827 port_number = port1.port_number;
9829 break;
9830 case 2:
9831 ZERO_STRUCT(port2);
9833 if (!pull_port_data_2(mem_ctx, &port2, in)) {
9834 return WERR_NOMEM;
9837 portname = port2.portname;
9838 hostaddress = port2.hostaddress;
9839 queue = port2.queue;
9840 protocol = port2.protocol;
9841 port_number = port2.port_number;
9843 break;
9844 default:
9845 DEBUG(1,("xcvtcp_addport: "
9846 "unknown version of port_data: %d\n", version));
9847 return WERR_UNKNOWN_PORT;
9850 /* create the device URI and call the add_port_hook() */
9852 switch (protocol) {
9853 case PROTOCOL_RAWTCP_TYPE:
9854 device_uri = talloc_asprintf(mem_ctx,
9855 "socket://%s:%d/", hostaddress,
9856 port_number);
9857 break;
9859 case PROTOCOL_LPR_TYPE:
9860 device_uri = talloc_asprintf(mem_ctx,
9861 "lpr://%s/%s", hostaddress, queue );
9862 break;
9864 default:
9865 return WERR_UNKNOWN_PORT;
9868 if (!device_uri) {
9869 return WERR_NOMEM;
9872 return add_port_hook(mem_ctx, token, portname, device_uri);
9875 /*******************************************************************
9876 *******************************************************************/
9878 struct xcv_api_table xcvtcp_cmds[] = {
9879 { "MonitorUI", xcvtcp_monitorui },
9880 { "AddPort", xcvtcp_addport},
9881 { NULL, NULL }
9884 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9885 struct security_token *token, const char *command,
9886 DATA_BLOB *inbuf,
9887 DATA_BLOB *outbuf,
9888 uint32_t *needed )
9890 int i;
9892 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9894 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9895 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9896 return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9899 return WERR_BADFUNC;
9902 /*******************************************************************
9903 *******************************************************************/
9904 #if 0 /* don't support management using the "Local Port" monitor */
9906 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9907 struct security_token *token, DATA_BLOB *in,
9908 DATA_BLOB *out, uint32_t *needed)
9910 const char *dllname = "localui.dll";
9912 *needed = (strlen(dllname)+1) * 2;
9914 if (out->length < *needed) {
9915 return WERR_INSUFFICIENT_BUFFER;
9918 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9919 return WERR_NOMEM;
9922 return WERR_OK;
9925 /*******************************************************************
9926 *******************************************************************/
9928 struct xcv_api_table xcvlocal_cmds[] = {
9929 { "MonitorUI", xcvlocal_monitorui },
9930 { NULL, NULL }
9932 #else
9933 struct xcv_api_table xcvlocal_cmds[] = {
9934 { NULL, NULL }
9936 #endif
9940 /*******************************************************************
9941 *******************************************************************/
9943 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9944 struct security_token *token, const char *command,
9945 DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9946 uint32_t *needed)
9948 int i;
9950 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9952 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9953 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9954 return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9956 return WERR_BADFUNC;
9959 /****************************************************************
9960 _spoolss_XcvData
9961 ****************************************************************/
9963 WERROR _spoolss_XcvData(struct pipes_struct *p,
9964 struct spoolss_XcvData *r)
9966 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9967 DATA_BLOB out_data = data_blob_null;
9968 WERROR werror;
9970 if (!Printer) {
9971 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9972 OUR_HANDLE(r->in.handle)));
9973 return WERR_BADFID;
9976 /* Has to be a handle to the TCP/IP port monitor */
9978 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9979 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9980 return WERR_BADFID;
9983 /* requires administrative access to the server */
9985 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9986 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9987 return WERR_ACCESS_DENIED;
9990 /* Allocate the outgoing buffer */
9992 if (r->in.out_data_size) {
9993 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9994 if (out_data.data == NULL) {
9995 return WERR_NOMEM;
9999 switch ( Printer->printer_type ) {
10000 case SPLHND_PORTMON_TCP:
10001 werror = process_xcvtcp_command(p->mem_ctx,
10002 p->session_info->security_token,
10003 r->in.function_name,
10004 &r->in.in_data, &out_data,
10005 r->out.needed);
10006 break;
10007 case SPLHND_PORTMON_LOCAL:
10008 werror = process_xcvlocal_command(p->mem_ctx,
10009 p->session_info->security_token,
10010 r->in.function_name,
10011 &r->in.in_data, &out_data,
10012 r->out.needed);
10013 break;
10014 default:
10015 werror = WERR_INVALID_PRINT_MONITOR;
10018 if (!W_ERROR_IS_OK(werror)) {
10019 return werror;
10022 *r->out.status_code = 0;
10024 if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10025 memcpy(r->out.out_data, out_data.data,
10026 MIN(r->in.out_data_size, out_data.length));
10029 return WERR_OK;
10032 /****************************************************************
10033 _spoolss_AddPrintProcessor
10034 ****************************************************************/
10036 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10037 struct spoolss_AddPrintProcessor *r)
10039 /* for now, just indicate success and ignore the add. We'll
10040 automatically set the winprint processor for printer
10041 entries later. Used to debug the LexMark Optra S 1855 PCL
10042 driver --jerry */
10044 return WERR_OK;
10047 /****************************************************************
10048 _spoolss_AddPort
10049 ****************************************************************/
10051 WERROR _spoolss_AddPort(struct pipes_struct *p,
10052 struct spoolss_AddPort *r)
10054 /* do what w2k3 does */
10056 return WERR_NOT_SUPPORTED;
10059 /****************************************************************
10060 _spoolss_GetPrinterDriver
10061 ****************************************************************/
10063 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10064 struct spoolss_GetPrinterDriver *r)
10066 p->rng_fault_state = true;
10067 return WERR_NOT_SUPPORTED;
10070 /****************************************************************
10071 _spoolss_ReadPrinter
10072 ****************************************************************/
10074 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10075 struct spoolss_ReadPrinter *r)
10077 p->rng_fault_state = true;
10078 return WERR_NOT_SUPPORTED;
10081 /****************************************************************
10082 _spoolss_WaitForPrinterChange
10083 ****************************************************************/
10085 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10086 struct spoolss_WaitForPrinterChange *r)
10088 p->rng_fault_state = true;
10089 return WERR_NOT_SUPPORTED;
10092 /****************************************************************
10093 _spoolss_ConfigurePort
10094 ****************************************************************/
10096 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10097 struct spoolss_ConfigurePort *r)
10099 p->rng_fault_state = true;
10100 return WERR_NOT_SUPPORTED;
10103 /****************************************************************
10104 _spoolss_DeletePort
10105 ****************************************************************/
10107 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10108 struct spoolss_DeletePort *r)
10110 p->rng_fault_state = true;
10111 return WERR_NOT_SUPPORTED;
10114 /****************************************************************
10115 _spoolss_CreatePrinterIC
10116 ****************************************************************/
10118 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10119 struct spoolss_CreatePrinterIC *r)
10121 p->rng_fault_state = true;
10122 return WERR_NOT_SUPPORTED;
10125 /****************************************************************
10126 _spoolss_PlayGDIScriptOnPrinterIC
10127 ****************************************************************/
10129 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10130 struct spoolss_PlayGDIScriptOnPrinterIC *r)
10132 p->rng_fault_state = true;
10133 return WERR_NOT_SUPPORTED;
10136 /****************************************************************
10137 _spoolss_DeletePrinterIC
10138 ****************************************************************/
10140 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10141 struct spoolss_DeletePrinterIC *r)
10143 p->rng_fault_state = true;
10144 return WERR_NOT_SUPPORTED;
10147 /****************************************************************
10148 _spoolss_AddPrinterConnection
10149 ****************************************************************/
10151 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10152 struct spoolss_AddPrinterConnection *r)
10154 p->rng_fault_state = true;
10155 return WERR_NOT_SUPPORTED;
10158 /****************************************************************
10159 _spoolss_DeletePrinterConnection
10160 ****************************************************************/
10162 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10163 struct spoolss_DeletePrinterConnection *r)
10165 p->rng_fault_state = true;
10166 return WERR_NOT_SUPPORTED;
10169 /****************************************************************
10170 _spoolss_PrinterMessageBox
10171 ****************************************************************/
10173 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10174 struct spoolss_PrinterMessageBox *r)
10176 p->rng_fault_state = true;
10177 return WERR_NOT_SUPPORTED;
10180 /****************************************************************
10181 _spoolss_AddMonitor
10182 ****************************************************************/
10184 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10185 struct spoolss_AddMonitor *r)
10187 p->rng_fault_state = true;
10188 return WERR_NOT_SUPPORTED;
10191 /****************************************************************
10192 _spoolss_DeleteMonitor
10193 ****************************************************************/
10195 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10196 struct spoolss_DeleteMonitor *r)
10198 p->rng_fault_state = true;
10199 return WERR_NOT_SUPPORTED;
10202 /****************************************************************
10203 _spoolss_DeletePrintProcessor
10204 ****************************************************************/
10206 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10207 struct spoolss_DeletePrintProcessor *r)
10209 p->rng_fault_state = true;
10210 return WERR_NOT_SUPPORTED;
10213 /****************************************************************
10214 _spoolss_AddPrintProvidor
10215 ****************************************************************/
10217 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10218 struct spoolss_AddPrintProvidor *r)
10220 p->rng_fault_state = true;
10221 return WERR_NOT_SUPPORTED;
10224 /****************************************************************
10225 _spoolss_DeletePrintProvidor
10226 ****************************************************************/
10228 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10229 struct spoolss_DeletePrintProvidor *r)
10231 p->rng_fault_state = true;
10232 return WERR_NOT_SUPPORTED;
10235 /****************************************************************
10236 _spoolss_FindFirstPrinterChangeNotification
10237 ****************************************************************/
10239 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10240 struct spoolss_FindFirstPrinterChangeNotification *r)
10242 p->rng_fault_state = true;
10243 return WERR_NOT_SUPPORTED;
10246 /****************************************************************
10247 _spoolss_FindNextPrinterChangeNotification
10248 ****************************************************************/
10250 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10251 struct spoolss_FindNextPrinterChangeNotification *r)
10253 p->rng_fault_state = true;
10254 return WERR_NOT_SUPPORTED;
10257 /****************************************************************
10258 _spoolss_RouterFindFirstPrinterChangeNotificationOld
10259 ****************************************************************/
10261 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10262 struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10264 p->rng_fault_state = true;
10265 return WERR_NOT_SUPPORTED;
10268 /****************************************************************
10269 _spoolss_ReplyOpenPrinter
10270 ****************************************************************/
10272 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10273 struct spoolss_ReplyOpenPrinter *r)
10275 p->rng_fault_state = true;
10276 return WERR_NOT_SUPPORTED;
10279 /****************************************************************
10280 _spoolss_RouterReplyPrinter
10281 ****************************************************************/
10283 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10284 struct spoolss_RouterReplyPrinter *r)
10286 p->rng_fault_state = true;
10287 return WERR_NOT_SUPPORTED;
10290 /****************************************************************
10291 _spoolss_ReplyClosePrinter
10292 ****************************************************************/
10294 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10295 struct spoolss_ReplyClosePrinter *r)
10297 p->rng_fault_state = true;
10298 return WERR_NOT_SUPPORTED;
10301 /****************************************************************
10302 _spoolss_AddPortEx
10303 ****************************************************************/
10305 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10306 struct spoolss_AddPortEx *r)
10308 p->rng_fault_state = true;
10309 return WERR_NOT_SUPPORTED;
10312 /****************************************************************
10313 _spoolss_RouterFindFirstPrinterChangeNotification
10314 ****************************************************************/
10316 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10317 struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10319 p->rng_fault_state = true;
10320 return WERR_NOT_SUPPORTED;
10323 /****************************************************************
10324 _spoolss_SpoolerInit
10325 ****************************************************************/
10327 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10328 struct spoolss_SpoolerInit *r)
10330 p->rng_fault_state = true;
10331 return WERR_NOT_SUPPORTED;
10334 /****************************************************************
10335 _spoolss_ResetPrinterEx
10336 ****************************************************************/
10338 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10339 struct spoolss_ResetPrinterEx *r)
10341 p->rng_fault_state = true;
10342 return WERR_NOT_SUPPORTED;
10345 /****************************************************************
10346 _spoolss_RouterReplyPrinterEx
10347 ****************************************************************/
10349 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10350 struct spoolss_RouterReplyPrinterEx *r)
10352 p->rng_fault_state = true;
10353 return WERR_NOT_SUPPORTED;
10356 /****************************************************************
10357 _spoolss_44
10358 ****************************************************************/
10360 WERROR _spoolss_44(struct pipes_struct *p,
10361 struct spoolss_44 *r)
10363 p->rng_fault_state = true;
10364 return WERR_NOT_SUPPORTED;
10367 /****************************************************************
10368 _spoolss_SetPort
10369 ****************************************************************/
10371 WERROR _spoolss_SetPort(struct pipes_struct *p,
10372 struct spoolss_SetPort *r)
10374 p->rng_fault_state = true;
10375 return WERR_NOT_SUPPORTED;
10378 /****************************************************************
10379 _spoolss_4a
10380 ****************************************************************/
10382 WERROR _spoolss_4a(struct pipes_struct *p,
10383 struct spoolss_4a *r)
10385 p->rng_fault_state = true;
10386 return WERR_NOT_SUPPORTED;
10389 /****************************************************************
10390 _spoolss_4b
10391 ****************************************************************/
10393 WERROR _spoolss_4b(struct pipes_struct *p,
10394 struct spoolss_4b *r)
10396 p->rng_fault_state = true;
10397 return WERR_NOT_SUPPORTED;
10400 /****************************************************************
10401 _spoolss_4c
10402 ****************************************************************/
10404 WERROR _spoolss_4c(struct pipes_struct *p,
10405 struct spoolss_4c *r)
10407 p->rng_fault_state = true;
10408 return WERR_NOT_SUPPORTED;
10411 /****************************************************************
10412 _spoolss_53
10413 ****************************************************************/
10415 WERROR _spoolss_53(struct pipes_struct *p,
10416 struct spoolss_53 *r)
10418 p->rng_fault_state = true;
10419 return WERR_NOT_SUPPORTED;
10422 /****************************************************************
10423 _spoolss_AddPerMachineConnection
10424 ****************************************************************/
10426 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
10427 struct spoolss_AddPerMachineConnection *r)
10429 p->rng_fault_state = true;
10430 return WERR_NOT_SUPPORTED;
10433 /****************************************************************
10434 _spoolss_DeletePerMachineConnection
10435 ****************************************************************/
10437 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
10438 struct spoolss_DeletePerMachineConnection *r)
10440 p->rng_fault_state = true;
10441 return WERR_NOT_SUPPORTED;
10444 /****************************************************************
10445 _spoolss_EnumPerMachineConnections
10446 ****************************************************************/
10448 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
10449 struct spoolss_EnumPerMachineConnections *r)
10451 p->rng_fault_state = true;
10452 return WERR_NOT_SUPPORTED;
10455 /****************************************************************
10456 _spoolss_5a
10457 ****************************************************************/
10459 WERROR _spoolss_5a(struct pipes_struct *p,
10460 struct spoolss_5a *r)
10462 p->rng_fault_state = true;
10463 return WERR_NOT_SUPPORTED;
10466 /****************************************************************
10467 _spoolss_5b
10468 ****************************************************************/
10470 WERROR _spoolss_5b(struct pipes_struct *p,
10471 struct spoolss_5b *r)
10473 p->rng_fault_state = true;
10474 return WERR_NOT_SUPPORTED;
10477 /****************************************************************
10478 _spoolss_5c
10479 ****************************************************************/
10481 WERROR _spoolss_5c(struct pipes_struct *p,
10482 struct spoolss_5c *r)
10484 p->rng_fault_state = true;
10485 return WERR_NOT_SUPPORTED;
10488 /****************************************************************
10489 _spoolss_5d
10490 ****************************************************************/
10492 WERROR _spoolss_5d(struct pipes_struct *p,
10493 struct spoolss_5d *r)
10495 p->rng_fault_state = true;
10496 return WERR_NOT_SUPPORTED;
10499 /****************************************************************
10500 _spoolss_5e
10501 ****************************************************************/
10503 WERROR _spoolss_5e(struct pipes_struct *p,
10504 struct spoolss_5e *r)
10506 p->rng_fault_state = true;
10507 return WERR_NOT_SUPPORTED;
10510 /****************************************************************
10511 _spoolss_5f
10512 ****************************************************************/
10514 WERROR _spoolss_5f(struct pipes_struct *p,
10515 struct spoolss_5f *r)
10517 p->rng_fault_state = true;
10518 return WERR_NOT_SUPPORTED;
10521 /****************************************************************
10522 _spoolss_60
10523 ****************************************************************/
10525 WERROR _spoolss_60(struct pipes_struct *p,
10526 struct spoolss_60 *r)
10528 p->rng_fault_state = true;
10529 return WERR_NOT_SUPPORTED;
10532 /****************************************************************
10533 _spoolss_61
10534 ****************************************************************/
10536 WERROR _spoolss_61(struct pipes_struct *p,
10537 struct spoolss_61 *r)
10539 p->rng_fault_state = true;
10540 return WERR_NOT_SUPPORTED;
10543 /****************************************************************
10544 _spoolss_62
10545 ****************************************************************/
10547 WERROR _spoolss_62(struct pipes_struct *p,
10548 struct spoolss_62 *r)
10550 p->rng_fault_state = true;
10551 return WERR_NOT_SUPPORTED;
10554 /****************************************************************
10555 _spoolss_63
10556 ****************************************************************/
10558 WERROR _spoolss_63(struct pipes_struct *p,
10559 struct spoolss_63 *r)
10561 p->rng_fault_state = true;
10562 return WERR_NOT_SUPPORTED;
10565 /****************************************************************
10566 _spoolss_64
10567 ****************************************************************/
10569 WERROR _spoolss_64(struct pipes_struct *p,
10570 struct spoolss_64 *r)
10572 p->rng_fault_state = true;
10573 return WERR_NOT_SUPPORTED;
10576 /****************************************************************
10577 _spoolss_65
10578 ****************************************************************/
10580 WERROR _spoolss_65(struct pipes_struct *p,
10581 struct spoolss_65 *r)
10583 p->rng_fault_state = true;
10584 return WERR_NOT_SUPPORTED;
10587 /****************************************************************
10588 _spoolss_GetCorePrinterDrivers
10589 ****************************************************************/
10591 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
10592 struct spoolss_GetCorePrinterDrivers *r)
10594 p->rng_fault_state = true;
10595 return WERR_NOT_SUPPORTED;
10598 /****************************************************************
10599 _spoolss_67
10600 ****************************************************************/
10602 WERROR _spoolss_67(struct pipes_struct *p,
10603 struct spoolss_67 *r)
10605 p->rng_fault_state = true;
10606 return WERR_NOT_SUPPORTED;
10609 /****************************************************************
10610 _spoolss_GetPrinterDriverPackagePath
10611 ****************************************************************/
10613 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
10614 struct spoolss_GetPrinterDriverPackagePath *r)
10616 p->rng_fault_state = true;
10617 return WERR_NOT_SUPPORTED;
10620 /****************************************************************
10621 _spoolss_69
10622 ****************************************************************/
10624 WERROR _spoolss_69(struct pipes_struct *p,
10625 struct spoolss_69 *r)
10627 p->rng_fault_state = true;
10628 return WERR_NOT_SUPPORTED;
10631 /****************************************************************
10632 _spoolss_6a
10633 ****************************************************************/
10635 WERROR _spoolss_6a(struct pipes_struct *p,
10636 struct spoolss_6a *r)
10638 p->rng_fault_state = true;
10639 return WERR_NOT_SUPPORTED;
10642 /****************************************************************
10643 _spoolss_6b
10644 ****************************************************************/
10646 WERROR _spoolss_6b(struct pipes_struct *p,
10647 struct spoolss_6b *r)
10649 p->rng_fault_state = true;
10650 return WERR_NOT_SUPPORTED;
10653 /****************************************************************
10654 _spoolss_6c
10655 ****************************************************************/
10657 WERROR _spoolss_6c(struct pipes_struct *p,
10658 struct spoolss_6c *r)
10660 p->rng_fault_state = true;
10661 return WERR_NOT_SUPPORTED;
10664 /****************************************************************
10665 _spoolss_6d
10666 ****************************************************************/
10668 WERROR _spoolss_6d(struct pipes_struct *p,
10669 struct spoolss_6d *r)
10671 p->rng_fault_state = true;
10672 return WERR_NOT_SUPPORTED;