s3-spoolss: Set DWORD values correctly.
[Samba/vl.git] / source3 / rpc_server / spoolss / srv_spoolss_nt.c
blob3a6fc357939f7b5a6464ead96d9fa36f2b39c9a2
1 /*
2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6 * Copyright (C) Jean François Micouleau 1998-2000,
7 * Copyright (C) Jeremy Allison 2001-2002,
8 * Copyright (C) Gerald Carter 2000-2004,
9 * Copyright (C) Tim Potter 2001-2002.
10 * Copyright (C) Guenther Deschner 2009-2010.
11 * Copyright (C) Andreas Schneider 2010.
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 3 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, see <http://www.gnu.org/licenses/>.
27 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
28 up, all the errors returned are DOS errors, not NT status codes. */
30 #include "includes.h"
31 #include "ntdomain.h"
32 #include "nt_printing.h"
33 #include "srv_spoolss_util.h"
34 #include "../librpc/gen_ndr/srv_spoolss.h"
35 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
36 #include "rpc_client/init_spoolss.h"
37 #include "rpc_client/cli_pipe.h"
38 #include "../libcli/security/security.h"
39 #include "librpc/gen_ndr/ndr_security.h"
40 #include "registry.h"
41 #include "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 "smbd/globals.h"
50 #include "auth.h"
51 #include "messages.h"
52 #include "rpc_server/spoolss/srv_spoolss_nt.h"
53 #include "util_tdb.h"
54 #include "libsmb/libsmb.h"
55 #include "printing/printer_list.h"
56 #include "../lib/tsocket/tsocket.h"
57 #include "rpc_client/cli_winreg_spoolss.h"
59 /* macros stolen from s4 spoolss server */
60 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
61 ((info)?ndr_size_##fn(info, level, 0):0)
63 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
64 ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
66 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
67 ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
69 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
71 #undef DBGC_CLASS
72 #define DBGC_CLASS DBGC_RPC_SRV
74 #ifndef MAX_OPEN_PRINTER_EXS
75 #define MAX_OPEN_PRINTER_EXS 50
76 #endif
78 struct notify_back_channel;
80 /* structure to store the printer handles */
81 /* and a reference to what it's pointing to */
82 /* and the notify info asked about */
83 /* that's the central struct */
84 struct printer_handle {
85 struct printer_handle *prev, *next;
86 bool document_started;
87 bool page_started;
88 uint32 jobid; /* jobid in printing backend */
89 int printer_type;
90 const char *servername;
91 fstring sharename;
92 uint32 type;
93 uint32 access_granted;
94 struct {
95 uint32 flags;
96 uint32 options;
97 fstring localmachine;
98 uint32 printerlocal;
99 struct spoolss_NotifyOption *option;
100 struct policy_handle cli_hnd;
101 struct notify_back_channel *cli_chan;
102 uint32 change;
103 /* are we in a FindNextPrinterChangeNotify() call? */
104 bool fnpcn;
105 struct messaging_context *msg_ctx;
106 } notify;
107 struct {
108 fstring machine;
109 fstring user;
110 } client;
112 /* devmode sent in the OpenPrinter() call */
113 struct spoolss_DeviceMode *devmode;
115 /* TODO cache the printer info2 structure */
116 struct spoolss_PrinterInfo2 *info2;
120 static struct printer_handle *printers_list;
122 struct printer_session_counter {
123 struct printer_session_counter *next;
124 struct printer_session_counter *prev;
126 int snum;
127 uint32_t counter;
130 static struct printer_session_counter *counter_list;
132 struct notify_back_channel {
133 struct notify_back_channel *prev, *next;
135 /* associated client */
136 struct sockaddr_storage client_address;
138 /* print notify back-channel pipe handle*/
139 struct rpc_pipe_client *cli_pipe;
140 uint32_t active_connections;
143 static struct notify_back_channel *back_channels;
145 /* Map generic permissions to printer object specific permissions */
147 const struct standard_mapping printer_std_mapping = {
148 PRINTER_READ,
149 PRINTER_WRITE,
150 PRINTER_EXECUTE,
151 PRINTER_ALL_ACCESS
154 /* Map generic permissions to print server object specific permissions */
156 const struct standard_mapping printserver_std_mapping = {
157 SERVER_READ,
158 SERVER_WRITE,
159 SERVER_EXECUTE,
160 SERVER_ALL_ACCESS
163 /* API table for Xcv Monitor functions */
165 struct xcv_api_table {
166 const char *name;
167 WERROR(*fn) (TALLOC_CTX *mem_ctx, struct security_token *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
170 static void prune_printername_cache(void);
172 /********************************************************************
173 * Canonicalize servername.
174 ********************************************************************/
176 static const char *canon_servername(const char *servername)
178 const char *pservername = servername;
179 while (*pservername == '\\') {
180 pservername++;
182 return pservername;
185 /* translate between internal status numbers and NT status numbers */
186 static int nt_printj_status(int v)
188 switch (v) {
189 case LPQ_QUEUED:
190 return 0;
191 case LPQ_PAUSED:
192 return JOB_STATUS_PAUSED;
193 case LPQ_SPOOLING:
194 return JOB_STATUS_SPOOLING;
195 case LPQ_PRINTING:
196 return JOB_STATUS_PRINTING;
197 case LPQ_ERROR:
198 return JOB_STATUS_ERROR;
199 case LPQ_DELETING:
200 return JOB_STATUS_DELETING;
201 case LPQ_OFFLINE:
202 return JOB_STATUS_OFFLINE;
203 case LPQ_PAPEROUT:
204 return JOB_STATUS_PAPEROUT;
205 case LPQ_PRINTED:
206 return JOB_STATUS_PRINTED;
207 case LPQ_DELETED:
208 return JOB_STATUS_DELETED;
209 case LPQ_BLOCKED:
210 return JOB_STATUS_BLOCKED_DEVQ;
211 case LPQ_USER_INTERVENTION:
212 return JOB_STATUS_USER_INTERVENTION;
214 return 0;
217 static int nt_printq_status(int v)
219 switch (v) {
220 case LPQ_PAUSED:
221 return PRINTER_STATUS_PAUSED;
222 case LPQ_QUEUED:
223 case LPQ_SPOOLING:
224 case LPQ_PRINTING:
225 return 0;
227 return 0;
230 /***************************************************************************
231 Disconnect from the client
232 ****************************************************************************/
234 static void srv_spoolss_replycloseprinter(int snum,
235 struct printer_handle *prn_hnd)
237 WERROR result;
238 NTSTATUS status;
241 * Tell the specific printing tdb we no longer want messages for this printer
242 * by deregistering our PID.
245 if (!print_notify_deregister_pid(snum)) {
246 DEBUG(0, ("Failed to register our pid for printer %s\n",
247 lp_const_servicename(snum)));
250 /* weird if the test succeeds !!! */
251 if (prn_hnd->notify.cli_chan == NULL ||
252 prn_hnd->notify.cli_chan->cli_pipe == NULL ||
253 prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
254 prn_hnd->notify.cli_chan->active_connections == 0) {
255 DEBUG(0, ("Trying to close unexisting backchannel!\n"));
256 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
257 TALLOC_FREE(prn_hnd->notify.cli_chan);
258 return;
261 status = dcerpc_spoolss_ReplyClosePrinter(
262 prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
263 talloc_tos(),
264 &prn_hnd->notify.cli_hnd,
265 &result);
266 if (!NT_STATUS_IS_OK(status)) {
267 DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
268 nt_errstr(status)));
269 result = ntstatus_to_werror(status);
270 } else if (!W_ERROR_IS_OK(result)) {
271 DEBUG(0, ("reply_close_printer failed [%s].\n",
272 win_errstr(result)));
275 /* if it's the last connection, deconnect the IPC$ share */
276 if (prn_hnd->notify.cli_chan->active_connections == 1) {
278 cli_shutdown(rpc_pipe_np_smb_conn(prn_hnd->notify.cli_chan->cli_pipe));
279 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
280 TALLOC_FREE(prn_hnd->notify.cli_chan);
282 if (prn_hnd->notify.msg_ctx != NULL) {
283 messaging_deregister(prn_hnd->notify.msg_ctx,
284 MSG_PRINTER_NOTIFY2, NULL);
288 if (prn_hnd->notify.cli_chan) {
289 prn_hnd->notify.cli_chan->active_connections--;
290 prn_hnd->notify.cli_chan = NULL;
294 /****************************************************************************
295 Functions to free a printer entry datastruct.
296 ****************************************************************************/
298 static int printer_entry_destructor(struct printer_handle *Printer)
300 if (Printer->notify.cli_chan != NULL &&
301 Printer->notify.cli_chan->active_connections > 0) {
302 int snum = -1;
304 switch(Printer->printer_type) {
305 case SPLHND_SERVER:
306 srv_spoolss_replycloseprinter(snum, Printer);
307 break;
309 case SPLHND_PRINTER:
310 snum = print_queue_snum(Printer->sharename);
311 if (snum != -1) {
312 srv_spoolss_replycloseprinter(snum, Printer);
314 break;
315 default:
316 break;
320 Printer->notify.flags=0;
321 Printer->notify.options=0;
322 Printer->notify.localmachine[0]='\0';
323 Printer->notify.printerlocal=0;
324 TALLOC_FREE(Printer->notify.option);
325 TALLOC_FREE(Printer->devmode);
327 /* Remove from the internal list. */
328 DLIST_REMOVE(printers_list, Printer);
329 return 0;
332 /****************************************************************************
333 find printer index by handle
334 ****************************************************************************/
336 static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
337 struct policy_handle *hnd)
339 struct printer_handle *find_printer = NULL;
341 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
342 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
343 return NULL;
346 return find_printer;
349 /****************************************************************************
350 Close printer index by handle.
351 ****************************************************************************/
353 static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
355 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
357 if (!Printer) {
358 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
359 OUR_HANDLE(hnd)));
360 return false;
363 close_policy_hnd(p, hnd);
365 return true;
368 /****************************************************************************
369 Delete a printer given a handle.
370 ****************************************************************************/
372 static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
373 const char *sharename,
374 struct messaging_context *msg_ctx)
376 char *cmd = lp_deleteprinter_cmd();
377 char *command = NULL;
378 int ret;
379 bool is_print_op = false;
381 /* can't fail if we don't try */
383 if ( !*cmd )
384 return WERR_OK;
386 command = talloc_asprintf(ctx,
387 "%s \"%s\"",
388 cmd, sharename);
389 if (!command) {
390 return WERR_NOMEM;
392 if ( token )
393 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
395 DEBUG(10,("Running [%s]\n", command));
397 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
399 if ( is_print_op )
400 become_root();
402 if ( (ret = smbrun(command, NULL)) == 0 ) {
403 /* Tell everyone we updated smb.conf. */
404 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
407 if ( is_print_op )
408 unbecome_root();
410 /********** END SePrintOperatorPrivlege BLOCK **********/
412 DEBUGADD(10,("returned [%d]\n", ret));
414 TALLOC_FREE(command);
416 if (ret != 0)
417 return WERR_BADFID; /* What to return here? */
419 return WERR_OK;
422 /****************************************************************************
423 Delete a printer given a handle.
424 ****************************************************************************/
426 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
428 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
429 WERROR result;
431 if (!Printer) {
432 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
433 OUR_HANDLE(hnd)));
434 return WERR_BADFID;
438 * It turns out that Windows allows delete printer on a handle
439 * opened by an admin user, then used on a pipe handle created
440 * by an anonymous user..... but they're working on security.... riiight !
441 * JRA.
444 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
445 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
446 return WERR_ACCESS_DENIED;
449 /* this does not need a become root since the access check has been
450 done on the handle already */
452 result = winreg_delete_printer_key_internal(p->mem_ctx,
453 get_session_info_system(),
454 p->msg_ctx,
455 Printer->sharename,
456 "");
457 if (!W_ERROR_IS_OK(result)) {
458 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
459 return WERR_BADFID;
462 result = delete_printer_hook(p->mem_ctx, p->session_info->security_token,
463 Printer->sharename, p->msg_ctx);
464 if (!W_ERROR_IS_OK(result)) {
465 return result;
467 prune_printername_cache();
468 return WERR_OK;
471 /****************************************************************************
472 Return the snum of a printer corresponding to an handle.
473 ****************************************************************************/
475 static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
476 int *number, struct share_params **params)
478 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
480 if (!Printer) {
481 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
482 OUR_HANDLE(hnd)));
483 return false;
486 switch (Printer->printer_type) {
487 case SPLHND_PRINTER:
488 DEBUG(4,("short name:%s\n", Printer->sharename));
489 *number = print_queue_snum(Printer->sharename);
490 return (*number != -1);
491 case SPLHND_SERVER:
492 return false;
493 default:
494 return false;
498 /****************************************************************************
499 Set printer handle type.
500 Check if it's \\server or \\server\printer
501 ****************************************************************************/
503 static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
505 DEBUG(3,("Setting printer type=%s\n", handlename));
507 /* it's a print server */
508 if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
509 DEBUGADD(4,("Printer is a print server\n"));
510 Printer->printer_type = SPLHND_SERVER;
512 /* it's a printer (set_printer_hnd_name() will handle port monitors */
513 else {
514 DEBUGADD(4,("Printer is a printer\n"));
515 Printer->printer_type = SPLHND_PRINTER;
518 return true;
521 static void prune_printername_cache_fn(const char *key, const char *value,
522 time_t timeout, void *private_data)
524 gencache_del(key);
527 static void prune_printername_cache(void)
529 gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
532 /****************************************************************************
533 Set printer handle name.. Accept names like \\server, \\server\printer,
534 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
535 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
536 XcvDataPort() interface.
537 ****************************************************************************/
539 static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
540 const struct auth_session_info *session_info,
541 struct messaging_context *msg_ctx,
542 struct printer_handle *Printer,
543 const char *handlename)
545 int snum;
546 int n_services=lp_numservices();
547 char *aprinter;
548 const char *printername;
549 const char *servername = NULL;
550 fstring sname;
551 bool found = false;
552 struct spoolss_PrinterInfo2 *info2 = NULL;
553 WERROR result;
554 char *p;
557 * Hopefully nobody names his printers like this. Maybe \ or ,
558 * are illegal in printer names even?
560 const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
561 char *cache_key;
562 char *tmp;
564 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
565 (unsigned long)strlen(handlename)));
567 aprinter = discard_const_p(char, handlename);
568 if ( *handlename == '\\' ) {
569 servername = canon_servername(handlename);
570 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
571 *aprinter = '\0';
572 aprinter++;
574 if (!is_myname_or_ipaddr(servername)) {
575 return WERR_INVALID_PRINTER_NAME;
577 Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
578 if (Printer->servername == NULL) {
579 return WERR_NOMEM;
583 if (Printer->printer_type == SPLHND_SERVER) {
584 return WERR_OK;
587 if (Printer->printer_type != SPLHND_PRINTER) {
588 return WERR_INVALID_HANDLE;
591 DEBUGADD(5, ("searching for [%s]\n", aprinter));
593 p = strchr(aprinter, ',');
594 if (p != NULL) {
595 char *p2 = p;
596 p++;
597 if (*p == ' ') {
598 p++;
600 if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
601 *p2 = '\0';
602 } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
603 *p2 = '\0';
607 if (p) {
608 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
611 /* check for the Port Monitor Interface */
612 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
613 Printer->printer_type = SPLHND_PORTMON_TCP;
614 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
615 found = true;
617 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
618 Printer->printer_type = SPLHND_PORTMON_LOCAL;
619 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
620 found = true;
624 * With hundreds of printers, the "for" loop iterating all
625 * shares can be quite expensive, as it is done on every
626 * OpenPrinter. The loop maps "aprinter" to "sname", the
627 * result of which we cache in gencache.
630 cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s",
631 aprinter);
632 if ((cache_key != NULL) && gencache_get(cache_key, &tmp, NULL)) {
634 found = (strcmp(tmp, printer_not_found) != 0);
635 if (!found) {
636 DEBUG(4, ("Printer %s not found\n", aprinter));
637 SAFE_FREE(tmp);
638 return WERR_INVALID_PRINTER_NAME;
640 fstrcpy(sname, tmp);
641 SAFE_FREE(tmp);
644 /* Search all sharenames first as this is easier than pulling
645 the printer_info_2 off of disk. Don't use find_service() since
646 that calls out to map_username() */
648 /* do another loop to look for printernames */
649 for (snum = 0; !found && snum < n_services; snum++) {
650 const char *printer = lp_const_servicename(snum);
652 /* no point going on if this is not a printer */
653 if (!(lp_snum_ok(snum) && lp_print_ok(snum))) {
654 continue;
657 /* ignore [printers] share */
658 if (strequal(printer, "printers")) {
659 continue;
662 fstrcpy(sname, printer);
663 if (strequal(aprinter, printer)) {
664 found = true;
665 break;
668 /* no point looking up the printer object if
669 we aren't allowing printername != sharename */
670 if (lp_force_printername(snum)) {
671 continue;
674 result = winreg_get_printer_internal(mem_ctx,
675 session_info,
676 msg_ctx,
677 sname,
678 &info2);
679 if ( !W_ERROR_IS_OK(result) ) {
680 DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
681 sname, win_errstr(result)));
682 continue;
685 printername = strrchr(info2->printername, '\\');
686 if (printername == NULL) {
687 printername = info2->printername;
688 } else {
689 printername++;
692 if (strequal(printername, aprinter)) {
693 found = true;
694 break;
697 DEBUGADD(10, ("printername: %s\n", printername));
699 TALLOC_FREE(info2);
702 if ( !found ) {
703 if (cache_key != NULL) {
704 gencache_set(cache_key, printer_not_found,
705 time(NULL)+300);
706 TALLOC_FREE(cache_key);
708 DEBUGADD(4,("Printer not found\n"));
709 return WERR_INVALID_PRINTER_NAME;
712 if (cache_key != NULL) {
713 gencache_set(cache_key, sname, time(NULL)+300);
714 TALLOC_FREE(cache_key);
717 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
719 strlcpy(Printer->sharename, sname, sizeof(Printer->sharename));
721 return WERR_OK;
724 /****************************************************************************
725 Find first available printer slot. creates a printer handle for you.
726 ****************************************************************************/
728 static WERROR open_printer_hnd(struct pipes_struct *p,
729 struct policy_handle *hnd,
730 const char *name,
731 uint32_t access_granted)
733 struct printer_handle *new_printer;
734 WERROR result;
736 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
738 new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
739 if (new_printer == NULL) {
740 return WERR_NOMEM;
742 talloc_set_destructor(new_printer, printer_entry_destructor);
744 /* This also steals the printer_handle on the policy_handle */
745 if (!create_policy_hnd(p, hnd, new_printer)) {
746 TALLOC_FREE(new_printer);
747 return WERR_INVALID_HANDLE;
750 /* Add to the internal list. */
751 DLIST_ADD(printers_list, new_printer);
753 new_printer->notify.option=NULL;
755 if (!set_printer_hnd_printertype(new_printer, name)) {
756 close_printer_handle(p, hnd);
757 return WERR_INVALID_HANDLE;
760 result = set_printer_hnd_name(p->mem_ctx,
761 get_session_info_system(),
762 p->msg_ctx,
763 new_printer, name);
764 if (!W_ERROR_IS_OK(result)) {
765 close_printer_handle(p, hnd);
766 return result;
769 new_printer->access_granted = access_granted;
771 DEBUG(5, ("%d printer handles active\n",
772 (int)num_pipe_handles(p)));
774 return WERR_OK;
777 /***************************************************************************
778 check to see if the client motify handle is monitoring the notification
779 given by (notify_type, notify_field).
780 **************************************************************************/
782 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
783 uint16_t notify_field)
785 return true;
788 static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
789 uint16_t notify_field)
791 struct spoolss_NotifyOption *option = p->notify.option;
792 uint32_t i, j;
795 * Flags should always be zero when the change notify
796 * is registered by the client's spooler. A user Win32 app
797 * might use the flags though instead of the NOTIFY_OPTION_INFO
798 * --jerry
801 if (!option) {
802 return false;
805 if (p->notify.flags)
806 return is_monitoring_event_flags(
807 p->notify.flags, notify_type, notify_field);
809 for (i = 0; i < option->count; i++) {
811 /* Check match for notify_type */
813 if (option->types[i].type != notify_type)
814 continue;
816 /* Check match for field */
818 for (j = 0; j < option->types[i].count; j++) {
819 if (option->types[i].fields[j].field == notify_field) {
820 return true;
825 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
826 p->servername, p->sharename, notify_type, notify_field));
828 return false;
831 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
832 _data->data.integer[0] = _integer; \
833 _data->data.integer[1] = 0;
836 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
837 _data->data.string.string = talloc_strdup(mem_ctx, _p); \
838 if (!_data->data.string.string) {\
839 _data->data.string.size = 0; \
841 _data->data.string.size = strlen_m_term(_p) * 2;
843 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
844 _data->data.devmode.devmode = _devmode;
846 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
847 _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
848 if (!_data->data.sd.sd) { \
849 _data->data.sd.sd_size = 0; \
851 _data->data.sd.sd_size = \
852 ndr_size_security_descriptor(_data->data.sd.sd, 0);
854 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
855 struct tm *t,
856 const char **pp,
857 uint32_t *plen)
859 struct spoolss_Time st;
860 uint32_t len = 16;
861 char *p;
863 if (!init_systemtime(&st, t)) {
864 return;
867 p = talloc_array(mem_ctx, char, len);
868 if (!p) {
869 return;
873 * Systemtime must be linearized as a set of UINT16's.
874 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
877 SSVAL(p, 0, st.year);
878 SSVAL(p, 2, st.month);
879 SSVAL(p, 4, st.day_of_week);
880 SSVAL(p, 6, st.day);
881 SSVAL(p, 8, st.hour);
882 SSVAL(p, 10, st.minute);
883 SSVAL(p, 12, st.second);
884 SSVAL(p, 14, st.millisecond);
886 *pp = p;
887 *plen = len;
890 /* Convert a notification message to a struct spoolss_Notify */
892 static void notify_one_value(struct spoolss_notify_msg *msg,
893 struct spoolss_Notify *data,
894 TALLOC_CTX *mem_ctx)
896 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
899 static void notify_string(struct spoolss_notify_msg *msg,
900 struct spoolss_Notify *data,
901 TALLOC_CTX *mem_ctx)
903 /* The length of the message includes the trailing \0 */
905 data->data.string.size = msg->len * 2;
906 data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
907 if (!data->data.string.string) {
908 data->data.string.size = 0;
909 return;
913 static void notify_system_time(struct spoolss_notify_msg *msg,
914 struct spoolss_Notify *data,
915 TALLOC_CTX *mem_ctx)
917 data->data.string.string = NULL;
918 data->data.string.size = 0;
920 if (msg->len != sizeof(time_t)) {
921 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
922 msg->len));
923 return;
926 init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
927 &data->data.string.string,
928 &data->data.string.size);
931 struct notify2_message_table {
932 const char *name;
933 void (*fn)(struct spoolss_notify_msg *msg,
934 struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
937 static struct notify2_message_table printer_notify_table[] = {
938 /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
939 /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
940 /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
941 /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
942 /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
943 /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
944 /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
945 /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
946 /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
947 /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
948 /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
949 /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
950 /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
951 /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
952 /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
953 /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
954 /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
955 /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
956 /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
959 static struct notify2_message_table job_notify_table[] = {
960 /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
961 /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
962 /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
963 /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
964 /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
965 /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
966 /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
967 /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
968 /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
969 /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
970 /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
971 /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
972 /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
973 /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
974 /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
975 /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
976 /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
977 /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
978 /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
979 /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
980 /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
981 /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
982 /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
983 /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
987 /***********************************************************************
988 Allocate talloc context for container object
989 **********************************************************************/
991 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
993 if ( !ctr )
994 return;
996 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
998 return;
1001 /***********************************************************************
1002 release all allocated memory and zero out structure
1003 **********************************************************************/
1005 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1007 if ( !ctr )
1008 return;
1010 if ( ctr->ctx )
1011 talloc_destroy(ctr->ctx);
1013 ZERO_STRUCTP(ctr);
1015 return;
1018 /***********************************************************************
1019 **********************************************************************/
1021 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1023 if ( !ctr )
1024 return NULL;
1026 return ctr->ctx;
1029 /***********************************************************************
1030 **********************************************************************/
1032 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1034 if ( !ctr || !ctr->msg_groups )
1035 return NULL;
1037 if ( idx >= ctr->num_groups )
1038 return NULL;
1040 return &ctr->msg_groups[idx];
1044 /***********************************************************************
1045 How many groups of change messages do we have ?
1046 **********************************************************************/
1048 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1050 if ( !ctr )
1051 return 0;
1053 return ctr->num_groups;
1056 /***********************************************************************
1057 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1058 **********************************************************************/
1060 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1062 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
1063 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
1064 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
1065 int i, new_slot;
1067 if ( !ctr || !msg )
1068 return 0;
1070 /* loop over all groups looking for a matching printer name */
1072 for ( i=0; i<ctr->num_groups; i++ ) {
1073 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1074 break;
1077 /* add a new group? */
1079 if ( i == ctr->num_groups ) {
1080 ctr->num_groups++;
1082 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1083 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1084 return 0;
1086 ctr->msg_groups = groups;
1088 /* clear the new entry and set the printer name */
1090 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1091 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1094 /* add the change messages; 'i' is the correct index now regardless */
1096 msg_grp = &ctr->msg_groups[i];
1098 msg_grp->num_msgs++;
1100 if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1101 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1102 return 0;
1104 msg_grp->msgs = msg_list;
1106 new_slot = msg_grp->num_msgs-1;
1107 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1109 /* need to allocate own copy of data */
1111 if ( msg->len != 0 )
1112 msg_grp->msgs[new_slot].notify.data = (char *)
1113 talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
1115 return ctr->num_groups;
1118 static void construct_info_data(struct spoolss_Notify *info_data,
1119 enum spoolss_NotifyType type,
1120 uint16_t field, int id);
1122 /***********************************************************************
1123 Send a change notication message on all handles which have a call
1124 back registered
1125 **********************************************************************/
1127 static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1128 struct printer_handle *prn_hnd,
1129 SPOOLSS_NOTIFY_MSG *messages,
1130 uint32_t num_msgs,
1131 struct spoolss_Notify **_notifies,
1132 int *_count)
1134 struct spoolss_Notify *notifies;
1135 SPOOLSS_NOTIFY_MSG *msg;
1136 int count = 0;
1137 uint32_t id;
1138 int i;
1140 notifies = talloc_zero_array(mem_ctx,
1141 struct spoolss_Notify, num_msgs);
1142 if (!notifies) {
1143 return ENOMEM;
1146 for (i = 0; i < num_msgs; i++) {
1148 msg = &messages[i];
1150 /* Are we monitoring this event? */
1152 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1153 continue;
1156 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1157 "for printer [%s]\n",
1158 msg->type, msg->field, prn_hnd->sharename));
1161 * if the is a printer notification handle and not a job
1162 * notification type, then set the id to 0.
1163 * Otherwise just use what was specified in the message.
1165 * When registering change notification on a print server
1166 * handle we always need to send back the id (snum) matching
1167 * the printer for which the change took place.
1168 * For change notify registered on a printer handle,
1169 * this does not matter and the id should be 0.
1171 * --jerry
1174 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1175 (prn_hnd->printer_type == SPLHND_PRINTER)) {
1176 id = 0;
1177 } else {
1178 id = msg->id;
1181 /* Convert unix jobid to smb jobid */
1183 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1184 id = sysjob_to_jobid(msg->id);
1186 if (id == -1) {
1187 DEBUG(3, ("no such unix jobid %d\n",
1188 msg->id));
1189 continue;
1193 construct_info_data(&notifies[count],
1194 msg->type, msg->field, id);
1196 switch(msg->type) {
1197 case PRINTER_NOTIFY_TYPE:
1198 if (printer_notify_table[msg->field].fn) {
1199 printer_notify_table[msg->field].fn(msg,
1200 &notifies[count], mem_ctx);
1202 break;
1204 case JOB_NOTIFY_TYPE:
1205 if (job_notify_table[msg->field].fn) {
1206 job_notify_table[msg->field].fn(msg,
1207 &notifies[count], mem_ctx);
1209 break;
1211 default:
1212 DEBUG(5, ("Unknown notification type %d\n",
1213 msg->type));
1214 continue;
1217 count++;
1220 *_notifies = notifies;
1221 *_count = count;
1223 return 0;
1226 static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1227 struct printer_handle *prn_hnd,
1228 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1230 struct spoolss_Notify *notifies;
1231 int count = 0;
1232 union spoolss_ReplyPrinterInfo info;
1233 struct spoolss_NotifyInfo info0;
1234 uint32_t reply_result;
1235 NTSTATUS status;
1236 WERROR werr;
1237 int ret;
1239 /* Is there notification on this handle? */
1240 if (prn_hnd->notify.cli_chan == NULL ||
1241 prn_hnd->notify.cli_chan->cli_pipe == NULL ||
1242 prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
1243 prn_hnd->notify.cli_chan->active_connections == 0) {
1244 return 0;
1247 DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1248 prn_hnd->servername, prn_hnd->sharename));
1250 /* For this printer? Print servers always receive notifications. */
1251 if ((prn_hnd->printer_type == SPLHND_PRINTER) &&
1252 (!strequal(msg_group->printername, prn_hnd->sharename))) {
1253 return 0;
1256 DEBUG(10,("Our printer\n"));
1258 /* build the array of change notifications */
1259 ret = build_notify2_messages(mem_ctx, prn_hnd,
1260 msg_group->msgs,
1261 msg_group->num_msgs,
1262 &notifies, &count);
1263 if (ret) {
1264 return ret;
1267 info0.version = 0x2;
1268 info0.flags = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1269 info0.count = count;
1270 info0.notifies = notifies;
1272 info.info0 = &info0;
1274 status = dcerpc_spoolss_RouterReplyPrinterEx(
1275 prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
1276 mem_ctx,
1277 &prn_hnd->notify.cli_hnd,
1278 prn_hnd->notify.change, /* color */
1279 prn_hnd->notify.flags,
1280 &reply_result,
1281 0, /* reply_type, must be 0 */
1282 info, &werr);
1283 if (!NT_STATUS_IS_OK(status)) {
1284 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1285 "failed: %s\n",
1286 prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1287 nt_errstr(status)));
1288 werr = ntstatus_to_werror(status);
1289 } else if (!W_ERROR_IS_OK(werr)) {
1290 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1291 "failed: %s\n",
1292 prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1293 win_errstr(werr)));
1295 switch (reply_result) {
1296 case 0:
1297 break;
1298 case PRINTER_NOTIFY_INFO_DISCARDED:
1299 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1300 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1301 break;
1302 default:
1303 break;
1306 return 0;
1309 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1311 struct printer_handle *p;
1312 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
1313 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1314 int ret;
1316 if ( !msg_group ) {
1317 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1318 return;
1321 if (!msg_group->msgs) {
1322 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1323 return;
1326 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1328 /* loop over all printers */
1330 for (p = printers_list; p; p = p->next) {
1331 ret = send_notify2_printer(mem_ctx, p, msg_group);
1332 if (ret) {
1333 goto done;
1337 done:
1338 DEBUG(8,("send_notify2_changes: Exit...\n"));
1339 return;
1342 /***********************************************************************
1343 **********************************************************************/
1345 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1348 uint32_t tv_sec, tv_usec;
1349 size_t offset = 0;
1351 /* Unpack message */
1353 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1354 msg->printer);
1356 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1357 &tv_sec, &tv_usec,
1358 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1360 if (msg->len == 0)
1361 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1362 &msg->notify.value[0], &msg->notify.value[1]);
1363 else
1364 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1365 &msg->len, &msg->notify.data);
1367 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1368 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1370 tv->tv_sec = tv_sec;
1371 tv->tv_usec = tv_usec;
1373 if (msg->len == 0)
1374 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1375 msg->notify.value[1]));
1376 else
1377 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1379 return true;
1382 /********************************************************************
1383 Receive a notify2 message list
1384 ********************************************************************/
1386 static void receive_notify2_message_list(struct messaging_context *msg,
1387 void *private_data,
1388 uint32_t msg_type,
1389 struct server_id server_id,
1390 DATA_BLOB *data)
1392 size_t msg_count, i;
1393 char *buf = (char *)data->data;
1394 char *msg_ptr;
1395 size_t msg_len;
1396 SPOOLSS_NOTIFY_MSG notify;
1397 SPOOLSS_NOTIFY_MSG_CTR messages;
1398 int num_groups;
1400 if (data->length < 4) {
1401 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1402 return;
1405 msg_count = IVAL(buf, 0);
1406 msg_ptr = buf + 4;
1408 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1410 if (msg_count == 0) {
1411 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1412 return;
1415 /* initialize the container */
1417 ZERO_STRUCT( messages );
1418 notify_msg_ctr_init( &messages );
1421 * build message groups for each printer identified
1422 * in a change_notify msg. Remember that a PCN message
1423 * includes the handle returned for the srv_spoolss_replyopenprinter()
1424 * call. Therefore messages are grouped according to printer handle.
1427 for ( i=0; i<msg_count; i++ ) {
1428 struct timeval msg_tv;
1430 if (msg_ptr + 4 - buf > data->length) {
1431 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1432 return;
1435 msg_len = IVAL(msg_ptr,0);
1436 msg_ptr += 4;
1438 if (msg_ptr + msg_len - buf > data->length) {
1439 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1440 return;
1443 /* unpack messages */
1445 ZERO_STRUCT( notify );
1446 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1447 msg_ptr += msg_len;
1449 /* add to correct list in container */
1451 notify_msg_ctr_addmsg( &messages, &notify );
1453 /* free memory that might have been allocated by notify2_unpack_msg() */
1455 if ( notify.len != 0 )
1456 SAFE_FREE( notify.notify.data );
1459 /* process each group of messages */
1461 num_groups = notify_msg_ctr_numgroups( &messages );
1462 for ( i=0; i<num_groups; i++ )
1463 send_notify2_changes( &messages, i );
1466 /* cleanup */
1468 DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1469 (uint32_t)msg_count ));
1471 notify_msg_ctr_destroy( &messages );
1473 return;
1476 /********************************************************************
1477 Send a message to ourself about new driver being installed
1478 so we can upgrade the information for each printer bound to this
1479 driver
1480 ********************************************************************/
1482 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1483 struct messaging_context *msg_ctx)
1485 int len = strlen(drivername);
1487 if (!len)
1488 return false;
1490 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1491 drivername));
1493 messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1494 MSG_PRINTER_DRVUPGRADE,
1495 (const uint8_t *)drivername, len+1);
1497 return true;
1500 void srv_spoolss_cleanup(void)
1502 struct printer_session_counter *session_counter;
1504 for (session_counter = counter_list;
1505 session_counter != NULL;
1506 session_counter = counter_list) {
1507 DLIST_REMOVE(counter_list, session_counter);
1508 TALLOC_FREE(session_counter);
1512 /**********************************************************************
1513 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1514 over all printers, upgrading ones as necessary
1515 **********************************************************************/
1517 void do_drv_upgrade_printer(struct messaging_context *msg,
1518 void *private_data,
1519 uint32_t msg_type,
1520 struct server_id server_id,
1521 DATA_BLOB *data)
1523 TALLOC_CTX *tmp_ctx;
1524 const struct auth_session_info *session_info = get_session_info_system();
1525 struct spoolss_PrinterInfo2 *pinfo2;
1526 WERROR result;
1527 const char *drivername;
1528 int snum;
1529 int n_services = lp_numservices();
1530 struct dcerpc_binding_handle *b = NULL;
1532 tmp_ctx = talloc_new(NULL);
1533 if (!tmp_ctx) return;
1535 drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1536 if (!drivername) {
1537 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1538 goto done;
1541 DEBUG(10, ("do_drv_upgrade_printer: "
1542 "Got message for new driver [%s]\n", drivername));
1544 /* Iterate the printer list */
1546 for (snum = 0; snum < n_services; snum++) {
1547 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1548 continue;
1551 /* ignore [printers] share */
1552 if (strequal(lp_const_servicename(snum), "printers")) {
1553 continue;
1556 if (b == NULL) {
1557 result = winreg_printer_binding_handle(tmp_ctx,
1558 session_info,
1559 msg,
1560 &b);
1561 if (!W_ERROR_IS_OK(result)) {
1562 break;
1566 result = winreg_get_printer(tmp_ctx, b,
1567 lp_const_servicename(snum),
1568 &pinfo2);
1570 if (!W_ERROR_IS_OK(result)) {
1571 continue;
1574 if (!pinfo2->drivername) {
1575 continue;
1578 if (strcmp(drivername, pinfo2->drivername) != 0) {
1579 continue;
1582 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1584 /* all we care about currently is the change_id */
1585 result = winreg_printer_update_changeid(tmp_ctx, b,
1586 pinfo2->printername);
1588 if (!W_ERROR_IS_OK(result)) {
1589 DEBUG(3, ("do_drv_upgrade_printer: "
1590 "Failed to update changeid [%s]\n",
1591 win_errstr(result)));
1595 /* all done */
1596 done:
1597 talloc_free(tmp_ctx);
1600 /********************************************************************
1601 Update the cache for all printq's with a registered client
1602 connection
1603 ********************************************************************/
1605 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1607 struct printer_handle *printer = printers_list;
1608 int snum;
1610 /* loop through all printers and update the cache where
1611 a client is connected */
1612 while (printer) {
1613 if ((printer->printer_type == SPLHND_PRINTER) &&
1614 ((printer->notify.cli_chan != NULL) &&
1615 (printer->notify.cli_chan->active_connections > 0))) {
1616 snum = print_queue_snum(printer->sharename);
1617 print_queue_status(msg_ctx, snum, NULL, NULL);
1620 printer = printer->next;
1623 return;
1626 /****************************************************************
1627 _spoolss_OpenPrinter
1628 ****************************************************************/
1630 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1631 struct spoolss_OpenPrinter *r)
1633 struct spoolss_OpenPrinterEx e;
1634 WERROR werr;
1636 ZERO_STRUCT(e.in.userlevel);
1638 e.in.printername = r->in.printername;
1639 e.in.datatype = r->in.datatype;
1640 e.in.devmode_ctr = r->in.devmode_ctr;
1641 e.in.access_mask = r->in.access_mask;
1642 e.in.level = 0;
1644 e.out.handle = r->out.handle;
1646 werr = _spoolss_OpenPrinterEx(p, &e);
1648 if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1649 /* OpenPrinterEx returns this for a bad
1650 * printer name. We must return WERR_INVALID_PRINTER_NAME
1651 * instead.
1653 werr = WERR_INVALID_PRINTER_NAME;
1656 return werr;
1659 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1660 struct spoolss_DeviceMode *orig,
1661 struct spoolss_DeviceMode **dest)
1663 struct spoolss_DeviceMode *dm;
1665 dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1666 if (!dm) {
1667 return WERR_NOMEM;
1670 /* copy all values, then duplicate strings and structs */
1671 *dm = *orig;
1673 dm->devicename = talloc_strdup(dm, orig->devicename);
1674 if (!dm->devicename) {
1675 return WERR_NOMEM;
1677 dm->formname = talloc_strdup(dm, orig->formname);
1678 if (!dm->formname) {
1679 return WERR_NOMEM;
1681 if (orig->driverextra_data.data) {
1682 dm->driverextra_data.data =
1683 (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1684 orig->driverextra_data.length);
1685 if (!dm->driverextra_data.data) {
1686 return WERR_NOMEM;
1690 *dest = dm;
1691 return WERR_OK;
1694 /****************************************************************
1695 _spoolss_OpenPrinterEx
1696 ****************************************************************/
1698 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1699 struct spoolss_OpenPrinterEx *r)
1701 int snum;
1702 char *raddr;
1703 char *rhost;
1704 struct printer_handle *Printer=NULL;
1705 WERROR result;
1706 int rc;
1708 if (!r->in.printername) {
1709 return WERR_INVALID_PARAM;
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->unix_token->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->unix_token->uid),
1816 p->session_info->info->domain_name,
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 */
1875 raddr = tsocket_address_inet_addr_string(p->remote_address,
1876 p->mem_ctx);
1877 if (raddr == NULL) {
1878 return WERR_NOMEM;
1881 rc = get_remote_hostname(p->remote_address,
1882 &rhost,
1883 p->mem_ctx);
1884 if (rc < 0) {
1885 return WERR_NOMEM;
1887 if (strequal(rhost, "UNKNOWN")) {
1888 rhost = raddr;
1891 if (!allow_access(lp_hostsdeny(snum), lp_hostsallow(snum),
1892 rhost, raddr)) {
1893 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1894 ZERO_STRUCTP(r->out.handle);
1895 return WERR_ACCESS_DENIED;
1898 if (!user_ok_token(uidtoname(p->session_info->unix_token->uid), NULL,
1899 p->session_info->security_token, snum) ||
1900 !print_access_check(p->session_info,
1901 p->msg_ctx,
1902 snum,
1903 r->in.access_mask)) {
1904 DEBUG(3, ("access DENIED for printer open\n"));
1905 close_printer_handle(p, r->out.handle);
1906 ZERO_STRUCTP(r->out.handle);
1907 return WERR_ACCESS_DENIED;
1910 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1911 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1912 close_printer_handle(p, r->out.handle);
1913 ZERO_STRUCTP(r->out.handle);
1914 return WERR_ACCESS_DENIED;
1917 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1918 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1919 else
1920 r->in.access_mask = PRINTER_ACCESS_USE;
1922 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1923 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1925 winreg_create_printer_internal(p->mem_ctx,
1926 get_session_info_system(),
1927 p->msg_ctx,
1928 lp_const_servicename(snum));
1930 break;
1932 default:
1933 /* sanity check to prevent programmer error */
1934 ZERO_STRUCTP(r->out.handle);
1935 return WERR_BADFID;
1938 Printer->access_granted = r->in.access_mask;
1941 * If the client sent a devmode in the OpenPrinter() call, then
1942 * save it here in case we get a job submission on this handle
1945 if ((Printer->printer_type != SPLHND_SERVER) &&
1946 r->in.devmode_ctr.devmode) {
1947 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1948 &Printer->devmode);
1951 #if 0 /* JERRY -- I'm doubtful this is really effective */
1952 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1953 optimization in Windows 2000 clients --jerry */
1955 if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1956 && (RA_WIN2K == get_remote_arch()) )
1958 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1959 usleep( 500000 );
1961 #endif
1963 return WERR_OK;
1966 /****************************************************************
1967 _spoolss_ClosePrinter
1968 ****************************************************************/
1970 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1971 struct spoolss_ClosePrinter *r)
1973 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1975 if (Printer && Printer->document_started) {
1976 struct spoolss_EndDocPrinter e;
1978 e.in.handle = r->in.handle;
1980 _spoolss_EndDocPrinter(p, &e);
1983 if (!close_printer_handle(p, r->in.handle))
1984 return WERR_BADFID;
1986 /* clear the returned printer handle. Observed behavior
1987 from Win2k server. Don't think this really matters.
1988 Previous code just copied the value of the closed
1989 handle. --jerry */
1991 ZERO_STRUCTP(r->out.handle);
1993 return WERR_OK;
1996 /****************************************************************
1997 _spoolss_DeletePrinter
1998 ****************************************************************/
2000 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
2001 struct spoolss_DeletePrinter *r)
2003 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2004 WERROR result;
2005 int snum;
2007 if (Printer && Printer->document_started) {
2008 struct spoolss_EndDocPrinter e;
2010 e.in.handle = r->in.handle;
2012 _spoolss_EndDocPrinter(p, &e);
2015 if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
2016 winreg_delete_printer_key_internal(p->mem_ctx,
2017 get_session_info_system(),
2018 p->msg_ctx,
2019 lp_const_servicename(snum),
2020 "");
2023 result = delete_printer_handle(p, r->in.handle);
2025 return result;
2028 /*******************************************************************
2029 * static function to lookup the version id corresponding to an
2030 * long architecture string
2031 ******************************************************************/
2033 static const struct print_architecture_table_node archi_table[]= {
2035 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
2036 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
2037 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
2038 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
2039 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
2040 {"Windows IA64", SPL_ARCH_IA64, 3 },
2041 {"Windows x64", SPL_ARCH_X64, 3 },
2042 {NULL, "", -1 }
2045 static const int drv_cversion[] = {SPOOLSS_DRIVER_VERSION_9X,
2046 SPOOLSS_DRIVER_VERSION_NT35,
2047 SPOOLSS_DRIVER_VERSION_NT4,
2048 SPOOLSS_DRIVER_VERSION_200X,
2049 -1};
2051 static int get_version_id(const char *arch)
2053 int i;
2055 for (i=0; archi_table[i].long_archi != NULL; i++)
2057 if (strcmp(arch, archi_table[i].long_archi) == 0)
2058 return (archi_table[i].version);
2061 return -1;
2064 /****************************************************************
2065 _spoolss_DeletePrinterDriver
2066 ****************************************************************/
2068 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2069 struct spoolss_DeletePrinterDriver *r)
2072 struct spoolss_DriverInfo8 *info = NULL;
2073 int version;
2074 WERROR status;
2075 struct dcerpc_binding_handle *b;
2076 TALLOC_CTX *tmp_ctx = NULL;
2077 int i;
2078 bool found;
2080 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2081 and not a printer admin, then fail */
2083 if ( (p->session_info->unix_token->uid != sec_initial_uid())
2084 && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2085 && !token_contains_name_in_list(
2086 uidtoname(p->session_info->unix_token->uid),
2087 p->session_info->info->domain_name,
2088 NULL,
2089 p->session_info->security_token,
2090 lp_printer_admin(-1)) )
2092 return WERR_ACCESS_DENIED;
2095 /* check that we have a valid driver name first */
2097 if ((version = get_version_id(r->in.architecture)) == -1) {
2098 return WERR_INVALID_ENVIRONMENT;
2101 tmp_ctx = talloc_new(p->mem_ctx);
2102 if (!tmp_ctx) {
2103 return WERR_NOMEM;
2106 status = winreg_printer_binding_handle(tmp_ctx,
2107 get_session_info_system(),
2108 p->msg_ctx,
2109 &b);
2110 if (!W_ERROR_IS_OK(status)) {
2111 goto done;
2114 for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2115 status = winreg_get_driver(tmp_ctx, b,
2116 r->in.architecture, r->in.driver,
2117 drv_cversion[i], &info);
2118 if (!W_ERROR_IS_OK(status)) {
2119 DEBUG(5, ("skipping del of driver with version %d\n",
2120 drv_cversion[i]));
2121 continue;
2123 found = true;
2125 if (printer_driver_in_use(tmp_ctx, b, info)) {
2126 status = WERR_PRINTER_DRIVER_IN_USE;
2127 goto done;
2130 status = winreg_del_driver(tmp_ctx, b, info, drv_cversion[i]);
2131 if (!W_ERROR_IS_OK(status)) {
2132 DEBUG(0, ("failed del of driver with version %d\n",
2133 drv_cversion[i]));
2134 goto done;
2137 if (found == false) {
2138 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2139 status = WERR_UNKNOWN_PRINTER_DRIVER;
2140 } else {
2141 status = WERR_OK;
2144 done:
2145 talloc_free(tmp_ctx);
2147 return status;
2150 static WERROR spoolss_dpd_version(TALLOC_CTX *mem_ctx,
2151 struct pipes_struct *p,
2152 struct spoolss_DeletePrinterDriverEx *r,
2153 struct dcerpc_binding_handle *b,
2154 struct spoolss_DriverInfo8 *info)
2156 WERROR status;
2157 bool delete_files;
2159 if (printer_driver_in_use(mem_ctx, b, info)) {
2160 status = WERR_PRINTER_DRIVER_IN_USE;
2161 goto done;
2165 * we have a couple of cases to consider.
2166 * (1) Are any files in use? If so and DPD_DELETE_ALL_FILES is set,
2167 * then the delete should fail if **any** files overlap with
2168 * other drivers
2169 * (2) If DPD_DELETE_UNUSED_FILES is set, then delete all
2170 * non-overlapping files
2171 * (3) If neither DPD_DELETE_ALL_FILES nor DPD_DELETE_UNUSED_FILES
2172 * are set, then do not delete any files
2173 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2176 delete_files = r->in.delete_flags
2177 & (DPD_DELETE_ALL_FILES | DPD_DELETE_UNUSED_FILES);
2180 if (delete_files) {
2181 bool in_use = printer_driver_files_in_use(mem_ctx, b, info);
2182 if (in_use && (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
2183 status = WERR_PRINTER_DRIVER_IN_USE;
2184 goto done;
2187 * printer_driver_files_in_use() has trimmed overlapping files
2188 * from info so they are not removed on DPD_DELETE_UNUSED_FILES
2193 status = winreg_del_driver(mem_ctx, b, info, info->version);
2194 if (!W_ERROR_IS_OK(status)) {
2195 goto done;
2199 * now delete any associated files if delete_files is
2200 * true. Even if this part failes, we return succes
2201 * because the driver doesn not exist any more
2203 if (delete_files) {
2204 delete_driver_files(get_session_info_system(), info);
2207 done:
2208 return status;
2211 /****************************************************************
2212 _spoolss_DeletePrinterDriverEx
2213 ****************************************************************/
2215 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2216 struct spoolss_DeletePrinterDriverEx *r)
2218 struct spoolss_DriverInfo8 *info = NULL;
2219 WERROR status;
2220 struct dcerpc_binding_handle *b;
2221 TALLOC_CTX *tmp_ctx = NULL;
2222 int i;
2223 bool found;
2225 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2226 and not a printer admin, then fail */
2228 if ( (p->session_info->unix_token->uid != sec_initial_uid())
2229 && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2230 && !token_contains_name_in_list(
2231 uidtoname(p->session_info->unix_token->uid),
2232 p->session_info->info->domain_name,
2233 NULL,
2234 p->session_info->security_token, lp_printer_admin(-1)) )
2236 return WERR_ACCESS_DENIED;
2239 /* check that we have a valid driver name first */
2240 if (get_version_id(r->in.architecture) == -1) {
2241 /* this is what NT returns */
2242 return WERR_INVALID_ENVIRONMENT;
2245 tmp_ctx = talloc_new(p->mem_ctx);
2246 if (!tmp_ctx) {
2247 return WERR_NOMEM;
2250 status = winreg_printer_binding_handle(tmp_ctx,
2251 get_session_info_system(),
2252 p->msg_ctx,
2253 &b);
2254 if (!W_ERROR_IS_OK(status)) {
2255 goto done;
2258 for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2259 if ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2260 && (drv_cversion[i] != r->in.version)) {
2261 continue;
2264 /* check if a driver with this version exists before delete */
2265 status = winreg_get_driver(tmp_ctx, b,
2266 r->in.architecture, r->in.driver,
2267 drv_cversion[i], &info);
2268 if (!W_ERROR_IS_OK(status)) {
2269 DEBUG(5, ("skipping del of driver with version %d\n",
2270 drv_cversion[i]));
2271 continue;
2273 found = true;
2275 status = spoolss_dpd_version(tmp_ctx, p, r, b, info);
2276 if (!W_ERROR_IS_OK(status)) {
2277 DEBUG(0, ("failed to delete driver with version %d\n",
2278 drv_cversion[i]));
2279 goto done;
2282 if (found == false) {
2283 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2284 status = WERR_UNKNOWN_PRINTER_DRIVER;
2285 } else {
2286 status = WERR_OK;
2289 done:
2290 talloc_free(tmp_ctx);
2291 return status;
2295 /********************************************************************
2296 GetPrinterData on a printer server Handle.
2297 ********************************************************************/
2299 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2300 const char *value,
2301 enum winreg_Type *type,
2302 union spoolss_PrinterData *data)
2304 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2306 if (!strcasecmp_m(value, "W3SvcInstalled")) {
2307 *type = REG_DWORD;
2308 SIVAL(&data->value, 0, 0x00);
2309 return WERR_OK;
2312 if (!strcasecmp_m(value, "BeepEnabled")) {
2313 *type = REG_DWORD;
2314 SIVAL(&data->value, 0, 0x00);
2315 return WERR_OK;
2318 if (!strcasecmp_m(value, "EventLog")) {
2319 *type = REG_DWORD;
2320 /* formally was 0x1b */
2321 SIVAL(&data->value, 0, 0x00);
2322 return WERR_OK;
2325 if (!strcasecmp_m(value, "NetPopup")) {
2326 *type = REG_DWORD;
2327 SIVAL(&data->value, 0, 0x00);
2328 return WERR_OK;
2331 if (!strcasecmp_m(value, "MajorVersion")) {
2332 *type = REG_DWORD;
2334 /* Windows NT 4.0 seems to not allow uploading of drivers
2335 to a server that reports 0x3 as the MajorVersion.
2336 need to investigate more how Win2k gets around this .
2337 -- jerry */
2339 if (RA_WINNT == get_remote_arch()) {
2340 SIVAL(&data->value, 0, 0x02);
2341 } else {
2342 SIVAL(&data->value, 0, 0x03);
2345 return WERR_OK;
2348 if (!strcasecmp_m(value, "MinorVersion")) {
2349 *type = REG_DWORD;
2350 SIVAL(&data->value, 0, 0x00);
2351 return WERR_OK;
2354 /* REG_BINARY
2355 * uint32_t size = 0x114
2356 * uint32_t major = 5
2357 * uint32_t minor = [0|1]
2358 * uint32_t build = [2195|2600]
2359 * extra unicode string = e.g. "Service Pack 3"
2361 if (!strcasecmp_m(value, "OSVersion")) {
2362 DATA_BLOB blob;
2363 enum ndr_err_code ndr_err;
2364 struct spoolss_OSVersion os;
2366 os.major = 5; /* Windows 2000 == 5.0 */
2367 os.minor = 0;
2368 os.build = 2195; /* build */
2369 os.extra_string = ""; /* leave extra string empty */
2371 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2372 (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2373 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2374 return WERR_GENERAL_FAILURE;
2377 *type = REG_BINARY;
2378 data->binary = blob;
2380 return WERR_OK;
2384 if (!strcasecmp_m(value, "DefaultSpoolDirectory")) {
2385 *type = REG_SZ;
2387 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2388 W_ERROR_HAVE_NO_MEMORY(data->string);
2390 return WERR_OK;
2393 if (!strcasecmp_m(value, "Architecture")) {
2394 *type = REG_SZ;
2395 data->string = talloc_strdup(mem_ctx,
2396 lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2397 W_ERROR_HAVE_NO_MEMORY(data->string);
2399 return WERR_OK;
2402 if (!strcasecmp_m(value, "DsPresent")) {
2403 *type = REG_DWORD;
2405 /* only show the publish check box if we are a
2406 member of a AD domain */
2408 if (lp_security() == SEC_ADS) {
2409 SIVAL(&data->value, 0, 0x01);
2410 } else {
2411 SIVAL(&data->value, 0, 0x00);
2413 return WERR_OK;
2416 if (!strcasecmp_m(value, "DNSMachineName")) {
2417 const char *hostname = get_mydnsfullname();
2419 if (!hostname) {
2420 return WERR_BADFILE;
2423 *type = REG_SZ;
2424 data->string = talloc_strdup(mem_ctx, hostname);
2425 W_ERROR_HAVE_NO_MEMORY(data->string);
2427 return WERR_OK;
2430 *type = REG_NONE;
2432 return WERR_INVALID_PARAM;
2435 /****************************************************************
2436 _spoolss_GetPrinterData
2437 ****************************************************************/
2439 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2440 struct spoolss_GetPrinterData *r)
2442 struct spoolss_GetPrinterDataEx r2;
2444 r2.in.handle = r->in.handle;
2445 r2.in.key_name = "PrinterDriverData";
2446 r2.in.value_name = r->in.value_name;
2447 r2.in.offered = r->in.offered;
2448 r2.out.type = r->out.type;
2449 r2.out.data = r->out.data;
2450 r2.out.needed = r->out.needed;
2452 return _spoolss_GetPrinterDataEx(p, &r2);
2455 /*********************************************************
2456 Connect to the client machine.
2457 **********************************************************/
2459 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2460 struct sockaddr_storage *client_ss, const char *remote_machine)
2462 NTSTATUS ret;
2463 struct cli_state *the_cli;
2464 struct sockaddr_storage rm_addr;
2465 char addr[INET6_ADDRSTRLEN];
2467 if ( is_zero_addr(client_ss) ) {
2468 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2469 remote_machine));
2470 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2471 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2472 return false;
2474 print_sockaddr(addr, sizeof(addr), &rm_addr);
2475 } else {
2476 rm_addr = *client_ss;
2477 print_sockaddr(addr, sizeof(addr), &rm_addr);
2478 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2479 addr));
2482 if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2483 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2484 addr));
2485 return false;
2488 /* setup the connection */
2489 ret = cli_full_connection( &the_cli, lp_netbios_name(), remote_machine,
2490 &rm_addr, 0, "IPC$", "IPC",
2491 "", /* username */
2492 "", /* domain */
2493 "", /* password */
2494 0, lp_client_signing());
2496 if ( !NT_STATUS_IS_OK( ret ) ) {
2497 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2498 remote_machine ));
2499 return false;
2502 if ( cli_state_protocol(the_cli) != PROTOCOL_NT1 ) {
2503 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2504 cli_shutdown(the_cli);
2505 return false;
2509 * Ok - we have an anonymous connection to the IPC$ share.
2510 * Now start the NT Domain stuff :-).
2513 ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2514 if (!NT_STATUS_IS_OK(ret)) {
2515 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2516 remote_machine, nt_errstr(ret)));
2517 cli_shutdown(the_cli);
2518 return false;
2521 return true;
2524 /***************************************************************************
2525 Connect to the client.
2526 ****************************************************************************/
2528 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2529 uint32_t localprinter,
2530 enum winreg_Type type,
2531 struct policy_handle *handle,
2532 struct notify_back_channel **_chan,
2533 struct sockaddr_storage *client_ss,
2534 struct messaging_context *msg_ctx)
2536 WERROR result;
2537 NTSTATUS status;
2538 struct notify_back_channel *chan;
2540 for (chan = back_channels; chan; chan = chan->next) {
2541 if (memcmp(&chan->client_address, client_ss,
2542 sizeof(struct sockaddr_storage)) == 0) {
2543 break;
2548 * If it's the first connection, contact the client
2549 * and connect to the IPC$ share anonymously
2551 if (!chan) {
2552 fstring unix_printer;
2554 /* the +2 is to strip the leading 2 backslashs */
2555 fstrcpy(unix_printer, printer + 2);
2557 chan = talloc_zero(NULL, struct notify_back_channel);
2558 if (!chan) {
2559 return false;
2561 chan->client_address = *client_ss;
2563 if (!spoolss_connect_to_client(&chan->cli_pipe, client_ss, unix_printer)) {
2564 TALLOC_FREE(chan);
2565 return false;
2568 DLIST_ADD(back_channels, chan);
2570 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2571 receive_notify2_message_list);
2574 if (chan->cli_pipe == NULL ||
2575 chan->cli_pipe->binding_handle == NULL) {
2576 DEBUG(0, ("srv_spoolss_replyopenprinter: error - "
2577 "NULL %s for printer %s\n",
2578 chan->cli_pipe == NULL ?
2579 "chan->cli_pipe" : "chan->cli_pipe->binding_handle",
2580 printer));
2581 return false;
2585 * Tell the specific printing tdb we want messages for this printer
2586 * by registering our PID.
2589 if (!print_notify_register_pid(snum)) {
2590 DEBUG(0, ("Failed to register our pid for printer %s\n",
2591 printer));
2594 status = dcerpc_spoolss_ReplyOpenPrinter(chan->cli_pipe->binding_handle,
2595 talloc_tos(),
2596 printer,
2597 localprinter,
2598 type,
2600 NULL,
2601 handle,
2602 &result);
2603 if (!NT_STATUS_IS_OK(status)) {
2604 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2605 result = ntstatus_to_werror(status);
2606 } else if (!W_ERROR_IS_OK(result)) {
2607 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2610 chan->active_connections++;
2611 *_chan = chan;
2613 return (W_ERROR_IS_OK(result));
2616 /****************************************************************
2617 ****************************************************************/
2619 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2620 const struct spoolss_NotifyOption *r)
2622 struct spoolss_NotifyOption *option;
2623 uint32_t i,k;
2625 if (!r) {
2626 return NULL;
2629 option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2630 if (!option) {
2631 return NULL;
2634 *option = *r;
2636 if (!option->count) {
2637 return option;
2640 option->types = talloc_zero_array(option,
2641 struct spoolss_NotifyOptionType, option->count);
2642 if (!option->types) {
2643 talloc_free(option);
2644 return NULL;
2647 for (i=0; i < option->count; i++) {
2648 option->types[i] = r->types[i];
2650 if (option->types[i].count) {
2651 option->types[i].fields = talloc_zero_array(option,
2652 union spoolss_Field, option->types[i].count);
2653 if (!option->types[i].fields) {
2654 talloc_free(option);
2655 return NULL;
2657 for (k=0; k<option->types[i].count; k++) {
2658 option->types[i].fields[k] =
2659 r->types[i].fields[k];
2664 return option;
2667 /****************************************************************
2668 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2670 * before replying OK: status=0 a rpc call is made to the workstation
2671 * asking ReplyOpenPrinter
2673 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2674 * called from api_spoolss_rffpcnex
2675 ****************************************************************/
2677 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2678 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2680 int snum = -1;
2681 struct spoolss_NotifyOption *option = r->in.notify_options;
2682 struct sockaddr_storage client_ss;
2683 ssize_t client_len;
2685 /* store the notify value in the printer struct */
2687 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2689 if (!Printer) {
2690 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2691 "Invalid handle (%s:%u:%u).\n",
2692 OUR_HANDLE(r->in.handle)));
2693 return WERR_BADFID;
2696 Printer->notify.flags = r->in.flags;
2697 Printer->notify.options = r->in.options;
2698 Printer->notify.printerlocal = r->in.printer_local;
2699 Printer->notify.msg_ctx = p->msg_ctx;
2701 TALLOC_FREE(Printer->notify.option);
2702 Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2704 fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2706 /* Connect to the client machine and send a ReplyOpenPrinter */
2708 if ( Printer->printer_type == SPLHND_SERVER)
2709 snum = -1;
2710 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2711 !get_printer_snum(p, r->in.handle, &snum, NULL) )
2712 return WERR_BADFID;
2714 DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2715 "remote_address is %s\n",
2716 tsocket_address_string(p->remote_address, p->mem_ctx)));
2718 if (!lp_print_notify_backchannel(snum)) {
2719 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2720 "backchannel disabled\n"));
2721 return WERR_SERVER_UNAVAILABLE;
2724 client_len = tsocket_address_bsd_sockaddr(p->remote_address,
2725 (struct sockaddr *) &client_ss,
2726 sizeof(struct sockaddr_storage));
2727 if (client_len < 0) {
2728 return WERR_NOMEM;
2731 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2732 Printer->notify.printerlocal, REG_SZ,
2733 &Printer->notify.cli_hnd,
2734 &Printer->notify.cli_chan,
2735 &client_ss, p->msg_ctx)) {
2736 return WERR_SERVER_UNAVAILABLE;
2739 return WERR_OK;
2742 /*******************************************************************
2743 * fill a notify_info_data with the servername
2744 ********************************************************************/
2746 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2747 int snum,
2748 struct spoolss_Notify *data,
2749 print_queue_struct *queue,
2750 struct spoolss_PrinterInfo2 *pinfo2,
2751 TALLOC_CTX *mem_ctx)
2753 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2756 /*******************************************************************
2757 * fill a notify_info_data with the printername (not including the servername).
2758 ********************************************************************/
2760 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2761 int snum,
2762 struct spoolss_Notify *data,
2763 print_queue_struct *queue,
2764 struct spoolss_PrinterInfo2 *pinfo2,
2765 TALLOC_CTX *mem_ctx)
2767 /* the notify name should not contain the \\server\ part */
2768 const char *p = strrchr(pinfo2->printername, '\\');
2770 if (!p) {
2771 p = pinfo2->printername;
2772 } else {
2773 p++;
2776 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2779 /*******************************************************************
2780 * fill a notify_info_data with the servicename
2781 ********************************************************************/
2783 static void spoolss_notify_share_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 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2793 /*******************************************************************
2794 * fill a notify_info_data with the port name
2795 ********************************************************************/
2797 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2798 int snum,
2799 struct spoolss_Notify *data,
2800 print_queue_struct *queue,
2801 struct spoolss_PrinterInfo2 *pinfo2,
2802 TALLOC_CTX *mem_ctx)
2804 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2807 /*******************************************************************
2808 * fill a notify_info_data with the printername
2809 * but it doesn't exist, have to see what to do
2810 ********************************************************************/
2812 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2813 int snum,
2814 struct spoolss_Notify *data,
2815 print_queue_struct *queue,
2816 struct spoolss_PrinterInfo2 *pinfo2,
2817 TALLOC_CTX *mem_ctx)
2819 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2822 /*******************************************************************
2823 * fill a notify_info_data with the comment
2824 ********************************************************************/
2826 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2827 int snum,
2828 struct spoolss_Notify *data,
2829 print_queue_struct *queue,
2830 struct spoolss_PrinterInfo2 *pinfo2,
2831 TALLOC_CTX *mem_ctx)
2833 const char *p;
2835 if (*pinfo2->comment == '\0') {
2836 p = lp_comment(snum);
2837 } else {
2838 p = pinfo2->comment;
2841 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2844 /*******************************************************************
2845 * fill a notify_info_data with the comment
2846 * location = "Room 1, floor 2, building 3"
2847 ********************************************************************/
2849 static void spoolss_notify_location(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 *loc = pinfo2->location;
2857 NTSTATUS status;
2859 status = printer_list_get_printer(mem_ctx,
2860 pinfo2->sharename,
2861 NULL,
2862 &loc,
2863 NULL);
2864 if (NT_STATUS_IS_OK(status)) {
2865 if (loc == NULL) {
2866 loc = pinfo2->location;
2870 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, loc);
2873 /*******************************************************************
2874 * fill a notify_info_data with the device mode
2875 * jfm:xxxx don't to it for know but that's a real problem !!!
2876 ********************************************************************/
2878 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2879 int snum,
2880 struct spoolss_Notify *data,
2881 print_queue_struct *queue,
2882 struct spoolss_PrinterInfo2 *pinfo2,
2883 TALLOC_CTX *mem_ctx)
2885 /* for a dummy implementation we have to zero the fields */
2886 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2889 /*******************************************************************
2890 * fill a notify_info_data with the separator file name
2891 ********************************************************************/
2893 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2894 int snum,
2895 struct spoolss_Notify *data,
2896 print_queue_struct *queue,
2897 struct spoolss_PrinterInfo2 *pinfo2,
2898 TALLOC_CTX *mem_ctx)
2900 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2903 /*******************************************************************
2904 * fill a notify_info_data with the print processor
2905 * jfm:xxxx return always winprint to indicate we don't do anything to it
2906 ********************************************************************/
2908 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2909 int snum,
2910 struct spoolss_Notify *data,
2911 print_queue_struct *queue,
2912 struct spoolss_PrinterInfo2 *pinfo2,
2913 TALLOC_CTX *mem_ctx)
2915 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2918 /*******************************************************************
2919 * fill a notify_info_data with the print processor options
2920 * jfm:xxxx send an empty string
2921 ********************************************************************/
2923 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2924 int snum,
2925 struct spoolss_Notify *data,
2926 print_queue_struct *queue,
2927 struct spoolss_PrinterInfo2 *pinfo2,
2928 TALLOC_CTX *mem_ctx)
2930 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2933 /*******************************************************************
2934 * fill a notify_info_data with the data type
2935 * jfm:xxxx always send RAW as data type
2936 ********************************************************************/
2938 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2939 int snum,
2940 struct spoolss_Notify *data,
2941 print_queue_struct *queue,
2942 struct spoolss_PrinterInfo2 *pinfo2,
2943 TALLOC_CTX *mem_ctx)
2945 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2948 /*******************************************************************
2949 * fill a notify_info_data with the security descriptor
2950 * jfm:xxxx send an null pointer to say no security desc
2951 * have to implement security before !
2952 ********************************************************************/
2954 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2955 int snum,
2956 struct spoolss_Notify *data,
2957 print_queue_struct *queue,
2958 struct spoolss_PrinterInfo2 *pinfo2,
2959 TALLOC_CTX *mem_ctx)
2961 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
2964 /*******************************************************************
2965 * fill a notify_info_data with the attributes
2966 * jfm:xxxx a samba printer is always shared
2967 ********************************************************************/
2969 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2970 int snum,
2971 struct spoolss_Notify *data,
2972 print_queue_struct *queue,
2973 struct spoolss_PrinterInfo2 *pinfo2,
2974 TALLOC_CTX *mem_ctx)
2976 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2979 /*******************************************************************
2980 * fill a notify_info_data with the priority
2981 ********************************************************************/
2983 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
2984 int snum,
2985 struct spoolss_Notify *data,
2986 print_queue_struct *queue,
2987 struct spoolss_PrinterInfo2 *pinfo2,
2988 TALLOC_CTX *mem_ctx)
2990 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
2993 /*******************************************************************
2994 * fill a notify_info_data with the default priority
2995 ********************************************************************/
2997 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
2998 int snum,
2999 struct spoolss_Notify *data,
3000 print_queue_struct *queue,
3001 struct spoolss_PrinterInfo2 *pinfo2,
3002 TALLOC_CTX *mem_ctx)
3004 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
3007 /*******************************************************************
3008 * fill a notify_info_data with the start time
3009 ********************************************************************/
3011 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
3012 int snum,
3013 struct spoolss_Notify *data,
3014 print_queue_struct *queue,
3015 struct spoolss_PrinterInfo2 *pinfo2,
3016 TALLOC_CTX *mem_ctx)
3018 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3021 /*******************************************************************
3022 * fill a notify_info_data with the until time
3023 ********************************************************************/
3025 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3026 int snum,
3027 struct spoolss_Notify *data,
3028 print_queue_struct *queue,
3029 struct spoolss_PrinterInfo2 *pinfo2,
3030 TALLOC_CTX *mem_ctx)
3032 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3035 /*******************************************************************
3036 * fill a notify_info_data with the status
3037 ********************************************************************/
3039 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3040 int snum,
3041 struct spoolss_Notify *data,
3042 print_queue_struct *queue,
3043 struct spoolss_PrinterInfo2 *pinfo2,
3044 TALLOC_CTX *mem_ctx)
3046 print_status_struct status;
3048 print_queue_length(msg_ctx, snum, &status);
3049 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3052 /*******************************************************************
3053 * fill a notify_info_data with the number of jobs queued
3054 ********************************************************************/
3056 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3057 int snum,
3058 struct spoolss_Notify *data,
3059 print_queue_struct *queue,
3060 struct spoolss_PrinterInfo2 *pinfo2,
3061 TALLOC_CTX *mem_ctx)
3063 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3064 data, print_queue_length(msg_ctx, snum, NULL));
3067 /*******************************************************************
3068 * fill a notify_info_data with the average ppm
3069 ********************************************************************/
3071 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3072 int snum,
3073 struct spoolss_Notify *data,
3074 print_queue_struct *queue,
3075 struct spoolss_PrinterInfo2 *pinfo2,
3076 TALLOC_CTX *mem_ctx)
3078 /* always respond 8 pages per minutes */
3079 /* a little hard ! */
3080 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3083 /*******************************************************************
3084 * fill a notify_info_data with username
3085 ********************************************************************/
3087 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3088 int snum,
3089 struct spoolss_Notify *data,
3090 print_queue_struct *queue,
3091 struct spoolss_PrinterInfo2 *pinfo2,
3092 TALLOC_CTX *mem_ctx)
3094 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3097 /*******************************************************************
3098 * fill a notify_info_data with job status
3099 ********************************************************************/
3101 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3102 int snum,
3103 struct spoolss_Notify *data,
3104 print_queue_struct *queue,
3105 struct spoolss_PrinterInfo2 *pinfo2,
3106 TALLOC_CTX *mem_ctx)
3108 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3111 /*******************************************************************
3112 * fill a notify_info_data with job name
3113 ********************************************************************/
3115 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3116 int snum,
3117 struct spoolss_Notify *data,
3118 print_queue_struct *queue,
3119 struct spoolss_PrinterInfo2 *pinfo2,
3120 TALLOC_CTX *mem_ctx)
3122 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3125 /*******************************************************************
3126 * fill a notify_info_data with job status
3127 ********************************************************************/
3129 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3130 int snum,
3131 struct spoolss_Notify *data,
3132 print_queue_struct *queue,
3133 struct spoolss_PrinterInfo2 *pinfo2,
3134 TALLOC_CTX *mem_ctx)
3137 * Now we're returning job status codes we just return a "" here. JRA.
3140 const char *p = "";
3142 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3143 p = "unknown";
3145 switch (queue->status) {
3146 case LPQ_QUEUED:
3147 p = "Queued";
3148 break;
3149 case LPQ_PAUSED:
3150 p = ""; /* NT provides the paused string */
3151 break;
3152 case LPQ_SPOOLING:
3153 p = "Spooling";
3154 break;
3155 case LPQ_PRINTING:
3156 p = "Printing";
3157 break;
3159 #endif /* NO LONGER NEEDED. */
3161 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3164 /*******************************************************************
3165 * fill a notify_info_data with job time
3166 ********************************************************************/
3168 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3169 int snum,
3170 struct spoolss_Notify *data,
3171 print_queue_struct *queue,
3172 struct spoolss_PrinterInfo2 *pinfo2,
3173 TALLOC_CTX *mem_ctx)
3175 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3178 /*******************************************************************
3179 * fill a notify_info_data with job size
3180 ********************************************************************/
3182 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3183 int snum,
3184 struct spoolss_Notify *data,
3185 print_queue_struct *queue,
3186 struct spoolss_PrinterInfo2 *pinfo2,
3187 TALLOC_CTX *mem_ctx)
3189 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3192 /*******************************************************************
3193 * fill a notify_info_data with page info
3194 ********************************************************************/
3195 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3196 int snum,
3197 struct spoolss_Notify *data,
3198 print_queue_struct *queue,
3199 struct spoolss_PrinterInfo2 *pinfo2,
3200 TALLOC_CTX *mem_ctx)
3202 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3205 /*******************************************************************
3206 * fill a notify_info_data with pages printed info.
3207 ********************************************************************/
3208 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3209 int snum,
3210 struct spoolss_Notify *data,
3211 print_queue_struct *queue,
3212 struct spoolss_PrinterInfo2 *pinfo2,
3213 TALLOC_CTX *mem_ctx)
3215 /* Add code when back-end tracks this */
3216 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3219 /*******************************************************************
3220 Fill a notify_info_data with job position.
3221 ********************************************************************/
3223 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3224 int snum,
3225 struct spoolss_Notify *data,
3226 print_queue_struct *queue,
3227 struct spoolss_PrinterInfo2 *pinfo2,
3228 TALLOC_CTX *mem_ctx)
3230 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3233 /*******************************************************************
3234 Fill a notify_info_data with submitted time.
3235 ********************************************************************/
3237 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3238 int snum,
3239 struct spoolss_Notify *data,
3240 print_queue_struct *queue,
3241 struct spoolss_PrinterInfo2 *pinfo2,
3242 TALLOC_CTX *mem_ctx)
3244 data->data.string.string = NULL;
3245 data->data.string.size = 0;
3247 init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3248 &data->data.string.string,
3249 &data->data.string.size);
3253 struct s_notify_info_data_table
3255 enum spoolss_NotifyType type;
3256 uint16_t field;
3257 const char *name;
3258 enum spoolss_NotifyTable variable_type;
3259 void (*fn) (struct messaging_context *msg_ctx,
3260 int snum, struct spoolss_Notify *data,
3261 print_queue_struct *queue,
3262 struct spoolss_PrinterInfo2 *pinfo2,
3263 TALLOC_CTX *mem_ctx);
3266 /* A table describing the various print notification constants and
3267 whether the notification data is a pointer to a variable sized
3268 buffer, a one value uint32_t or a two value uint32_t. */
3270 static const struct s_notify_info_data_table notify_info_data_table[] =
3272 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3273 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3274 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
3275 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3276 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3277 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
3278 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
3279 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3280 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
3281 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3282 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3283 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3284 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
3285 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
3286 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3287 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
3288 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3289 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3290 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
3291 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
3292 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
3293 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
3294 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
3295 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3296 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
3297 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3298 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINTER_NAME, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3299 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_MACHINE_NAME, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3300 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PORT_NAME, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3301 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_USER_NAME, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3302 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_NOTIFY_NAME, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3303 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DATATYPE, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3304 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINT_PROCESSOR, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3305 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PARAMETERS, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3306 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DRIVER_NAME, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3307 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DEVMODE, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3308 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
3309 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS_STRING, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
3310 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
3311 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DOCUMENT, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
3312 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRIORITY, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3313 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_POSITION, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
3314 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SUBMITTED, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
3315 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_START_TIME, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3316 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_UNTIL_TIME, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3317 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TIME, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
3318 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_PAGES, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
3319 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PAGES_PRINTED, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
3320 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_BYTES, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
3323 /*******************************************************************
3324 Return the variable_type of info_data structure.
3325 ********************************************************************/
3327 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3328 uint16_t field)
3330 int i=0;
3332 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3333 if ( (notify_info_data_table[i].type == type) &&
3334 (notify_info_data_table[i].field == field) ) {
3335 return notify_info_data_table[i].variable_type;
3339 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3341 return (enum spoolss_NotifyTable) 0;
3344 /****************************************************************************
3345 ****************************************************************************/
3347 static bool search_notify(enum spoolss_NotifyType type,
3348 uint16_t field,
3349 int *value)
3351 int i;
3353 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3354 if (notify_info_data_table[i].type == type &&
3355 notify_info_data_table[i].field == field &&
3356 notify_info_data_table[i].fn != NULL) {
3357 *value = i;
3358 return true;
3362 return false;
3365 /****************************************************************************
3366 ****************************************************************************/
3368 static void construct_info_data(struct spoolss_Notify *info_data,
3369 enum spoolss_NotifyType type,
3370 uint16_t field, int id)
3372 info_data->type = type;
3373 info_data->field.field = field;
3374 info_data->variable_type = variable_type_of_notify_info_data(type, field);
3375 info_data->job_id = id;
3378 /*******************************************************************
3380 * fill a notify_info struct with info asked
3382 ********************************************************************/
3384 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3385 struct printer_handle *print_hnd,
3386 struct spoolss_NotifyInfo *info,
3387 struct spoolss_PrinterInfo2 *pinfo2,
3388 int snum,
3389 const struct spoolss_NotifyOptionType *option_type,
3390 uint32_t id,
3391 TALLOC_CTX *mem_ctx)
3393 int field_num,j;
3394 enum spoolss_NotifyType type;
3395 uint16_t field;
3397 struct spoolss_Notify *current_data;
3399 type = option_type->type;
3401 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3402 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3403 option_type->count, lp_servicename(snum)));
3405 for(field_num=0; field_num < option_type->count; field_num++) {
3406 field = option_type->fields[field_num].field;
3408 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3410 if (!search_notify(type, field, &j) )
3411 continue;
3413 info->notifies = talloc_realloc(info, info->notifies,
3414 struct spoolss_Notify,
3415 info->count + 1);
3416 if (info->notifies == NULL) {
3417 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3418 return false;
3421 current_data = &info->notifies[info->count];
3423 construct_info_data(current_data, type, field, id);
3425 DEBUG(10, ("construct_notify_printer_info: "
3426 "calling [%s] snum=%d printername=[%s])\n",
3427 notify_info_data_table[j].name, snum,
3428 pinfo2->printername));
3430 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3431 NULL, pinfo2, mem_ctx);
3433 info->count++;
3436 return true;
3439 /*******************************************************************
3441 * fill a notify_info struct with info asked
3443 ********************************************************************/
3445 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3446 print_queue_struct *queue,
3447 struct spoolss_NotifyInfo *info,
3448 struct spoolss_PrinterInfo2 *pinfo2,
3449 int snum,
3450 const struct spoolss_NotifyOptionType *option_type,
3451 uint32_t id,
3452 TALLOC_CTX *mem_ctx)
3454 int field_num,j;
3455 enum spoolss_NotifyType type;
3456 uint16_t field;
3457 struct spoolss_Notify *current_data;
3459 DEBUG(4,("construct_notify_jobs_info\n"));
3461 type = option_type->type;
3463 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3464 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3465 option_type->count));
3467 for(field_num=0; field_num<option_type->count; field_num++) {
3468 field = option_type->fields[field_num].field;
3470 if (!search_notify(type, field, &j) )
3471 continue;
3473 info->notifies = talloc_realloc(info, info->notifies,
3474 struct spoolss_Notify,
3475 info->count + 1);
3476 if (info->notifies == NULL) {
3477 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3478 return false;
3481 current_data=&(info->notifies[info->count]);
3483 construct_info_data(current_data, type, field, id);
3484 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3485 queue, pinfo2, mem_ctx);
3486 info->count++;
3489 return true;
3493 * JFM: The enumeration is not that simple, it's even non obvious.
3495 * let's take an example: I want to monitor the PRINTER SERVER for
3496 * the printer's name and the number of jobs currently queued.
3497 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3498 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3500 * I have 3 printers on the back of my server.
3502 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3503 * structures.
3504 * Number Data Id
3505 * 1 printer 1 name 1
3506 * 2 printer 1 cjob 1
3507 * 3 printer 2 name 2
3508 * 4 printer 2 cjob 2
3509 * 5 printer 3 name 3
3510 * 6 printer 3 name 3
3512 * that's the print server case, the printer case is even worse.
3515 /*******************************************************************
3517 * enumerate all printers on the printserver
3518 * fill a notify_info struct with info asked
3520 ********************************************************************/
3522 static WERROR printserver_notify_info(struct pipes_struct *p,
3523 struct policy_handle *hnd,
3524 struct spoolss_NotifyInfo *info,
3525 TALLOC_CTX *mem_ctx)
3527 int snum;
3528 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3529 int n_services=lp_numservices();
3530 int i;
3531 struct spoolss_NotifyOption *option;
3532 struct spoolss_NotifyOptionType option_type;
3533 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3534 WERROR result;
3536 DEBUG(4,("printserver_notify_info\n"));
3538 if (!Printer)
3539 return WERR_BADFID;
3541 option = Printer->notify.option;
3543 info->version = 2;
3544 info->notifies = NULL;
3545 info->count = 0;
3547 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3548 sending a ffpcn() request first */
3550 if ( !option )
3551 return WERR_BADFID;
3553 for (i=0; i<option->count; i++) {
3554 option_type = option->types[i];
3556 if (option_type.type != PRINTER_NOTIFY_TYPE)
3557 continue;
3559 for (snum = 0; snum < n_services; snum++) {
3560 if (!lp_browseable(snum) ||
3561 !lp_snum_ok(snum) ||
3562 !lp_print_ok(snum)) {
3563 continue; /* skip */
3566 /* Maybe we should use the SYSTEM session_info here... */
3567 result = winreg_get_printer_internal(mem_ctx,
3568 get_session_info_system(),
3569 p->msg_ctx,
3570 lp_servicename(snum),
3571 &pinfo2);
3572 if (!W_ERROR_IS_OK(result)) {
3573 DEBUG(4, ("printserver_notify_info: "
3574 "Failed to get printer [%s]\n",
3575 lp_servicename(snum)));
3576 continue;
3580 construct_notify_printer_info(p->msg_ctx,
3581 Printer, info,
3582 pinfo2, snum,
3583 &option_type, snum,
3584 mem_ctx);
3586 TALLOC_FREE(pinfo2);
3590 #if 0
3592 * Debugging information, don't delete.
3595 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3596 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3597 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3599 for (i=0; i<info->count; i++) {
3600 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3601 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3602 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3604 #endif
3606 return WERR_OK;
3609 /*******************************************************************
3611 * fill a notify_info struct with info asked
3613 ********************************************************************/
3615 static WERROR printer_notify_info(struct pipes_struct *p,
3616 struct policy_handle *hnd,
3617 struct spoolss_NotifyInfo *info,
3618 TALLOC_CTX *mem_ctx)
3620 int snum;
3621 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3622 int i;
3623 uint32_t id;
3624 struct spoolss_NotifyOption *option;
3625 struct spoolss_NotifyOptionType option_type;
3626 int count,j;
3627 print_queue_struct *queue=NULL;
3628 print_status_struct status;
3629 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3630 WERROR result;
3632 DEBUG(4,("printer_notify_info\n"));
3634 if (!Printer)
3635 return WERR_BADFID;
3637 option = Printer->notify.option;
3638 id = 0x0;
3640 info->version = 2;
3641 info->notifies = NULL;
3642 info->count = 0;
3644 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3645 sending a ffpcn() request first */
3647 if ( !option )
3648 return WERR_BADFID;
3650 if (!get_printer_snum(p, hnd, &snum, NULL)) {
3651 return WERR_BADFID;
3654 /* Maybe we should use the SYSTEM session_info here... */
3655 result = winreg_get_printer_internal(mem_ctx,
3656 get_session_info_system(),
3657 p->msg_ctx,
3658 lp_servicename(snum), &pinfo2);
3659 if (!W_ERROR_IS_OK(result)) {
3660 return WERR_BADFID;
3664 * When sending a PRINTER_NOTIFY_FIELD_SERVER_NAME we should send the
3665 * correct servername.
3667 pinfo2->servername = talloc_strdup(pinfo2, Printer->servername);
3668 if (pinfo2->servername == NULL) {
3669 return WERR_NOMEM;
3672 for (i=0; i<option->count; i++) {
3673 option_type = option->types[i];
3675 switch (option_type.type) {
3676 case PRINTER_NOTIFY_TYPE:
3677 if (construct_notify_printer_info(p->msg_ctx,
3678 Printer, info,
3679 pinfo2, snum,
3680 &option_type, id,
3681 mem_ctx)) {
3682 id--;
3684 break;
3686 case JOB_NOTIFY_TYPE:
3688 count = print_queue_status(p->msg_ctx, snum, &queue,
3689 &status);
3691 for (j=0; j<count; j++) {
3692 construct_notify_jobs_info(p->msg_ctx,
3693 &queue[j], info,
3694 pinfo2, snum,
3695 &option_type,
3696 queue[j].job,
3697 mem_ctx);
3700 SAFE_FREE(queue);
3701 break;
3706 * Debugging information, don't delete.
3709 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3710 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3711 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3713 for (i=0; i<info->count; i++) {
3714 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3715 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3716 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3720 talloc_free(pinfo2);
3721 return WERR_OK;
3724 /****************************************************************
3725 _spoolss_RouterRefreshPrinterChangeNotify
3726 ****************************************************************/
3728 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3729 struct spoolss_RouterRefreshPrinterChangeNotify *r)
3731 struct spoolss_NotifyInfo *info;
3733 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3734 WERROR result = WERR_BADFID;
3736 /* we always have a spoolss_NotifyInfo struct */
3737 info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3738 if (!info) {
3739 result = WERR_NOMEM;
3740 goto done;
3743 *r->out.info = info;
3745 if (!Printer) {
3746 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3747 "Invalid handle (%s:%u:%u).\n",
3748 OUR_HANDLE(r->in.handle)));
3749 goto done;
3752 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3755 * We are now using the change value, and
3756 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3757 * I don't have a global notification system, I'm sending back all the
3758 * information even when _NOTHING_ has changed.
3761 /* We need to keep track of the change value to send back in
3762 RRPCN replies otherwise our updates are ignored. */
3764 Printer->notify.fnpcn = true;
3766 if (Printer->notify.cli_chan != NULL &&
3767 Printer->notify.cli_chan->active_connections > 0) {
3768 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3769 "Saving change value in request [%x]\n",
3770 r->in.change_low));
3771 Printer->notify.change = r->in.change_low;
3774 /* just ignore the spoolss_NotifyOption */
3776 switch (Printer->printer_type) {
3777 case SPLHND_SERVER:
3778 result = printserver_notify_info(p, r->in.handle,
3779 info, p->mem_ctx);
3780 break;
3782 case SPLHND_PRINTER:
3783 result = printer_notify_info(p, r->in.handle,
3784 info, p->mem_ctx);
3785 break;
3788 Printer->notify.fnpcn = false;
3790 done:
3791 return result;
3794 /********************************************************************
3795 ********************************************************************/
3797 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3798 const char *servername,
3799 const char *printername,
3800 const char **printername_p)
3802 /* FIXME: add lp_force_printername() */
3804 if (servername == NULL) {
3805 *printername_p = talloc_strdup(mem_ctx, printername);
3806 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3807 return WERR_OK;
3810 if (servername[0] == '\\' && servername[1] == '\\') {
3811 servername += 2;
3814 *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3815 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3817 return WERR_OK;
3820 /********************************************************************
3821 ********************************************************************/
3823 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3824 const char *printername)
3826 if (dm == NULL) {
3827 return;
3830 dm->devicename = talloc_strndup(dm, printername,
3831 MIN(strlen(printername), 31));
3834 /********************************************************************
3835 * construct_printer_info_0
3836 * fill a printer_info_0 struct
3837 ********************************************************************/
3839 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3840 const struct auth_session_info *session_info,
3841 struct messaging_context *msg_ctx,
3842 struct spoolss_PrinterInfo2 *info2,
3843 const char *servername,
3844 struct spoolss_PrinterInfo0 *r,
3845 int snum)
3847 int count;
3848 struct printer_session_counter *session_counter;
3849 struct timeval setuptime;
3850 print_status_struct status;
3851 WERROR result;
3853 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3854 if (!W_ERROR_IS_OK(result)) {
3855 return result;
3858 if (servername) {
3859 r->servername = talloc_strdup(mem_ctx, servername);
3860 W_ERROR_HAVE_NO_MEMORY(r->servername);
3861 } else {
3862 r->servername = NULL;
3865 count = print_queue_length(msg_ctx, snum, &status);
3867 /* check if we already have a counter for this printer */
3868 for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3869 if (session_counter->snum == snum)
3870 break;
3873 /* it's the first time, add it to the list */
3874 if (session_counter == NULL) {
3875 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3876 W_ERROR_HAVE_NO_MEMORY(session_counter);
3877 session_counter->snum = snum;
3878 session_counter->counter = 0;
3879 DLIST_ADD(counter_list, session_counter);
3882 /* increment it */
3883 session_counter->counter++;
3885 r->cjobs = count;
3886 r->total_jobs = 0;
3887 r->total_bytes = 0;
3889 get_startup_time(&setuptime);
3890 init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3892 /* JFM:
3893 * the global_counter should be stored in a TDB as it's common to all the clients
3894 * and should be zeroed on samba startup
3896 r->global_counter = session_counter->counter;
3897 r->total_pages = 0;
3898 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3899 SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3900 SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3901 r->free_build = SPOOLSS_RELEASE_BUILD;
3902 r->spooling = 0;
3903 r->max_spooling = 0;
3904 r->session_counter = session_counter->counter;
3905 r->num_error_out_of_paper = 0x0;
3906 r->num_error_not_ready = 0x0; /* number of print failure */
3907 r->job_error = 0x0;
3908 r->number_of_processors = 0x1;
3909 r->processor_type = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3910 r->high_part_total_bytes = 0x0;
3912 /* ChangeID in milliseconds*/
3913 winreg_printer_get_changeid_internal(mem_ctx, session_info, msg_ctx,
3914 info2->sharename, &r->change_id);
3916 r->last_error = WERR_OK;
3917 r->status = nt_printq_status(status.status);
3918 r->enumerate_network_printers = 0x0;
3919 r->c_setprinter = 0x0;
3920 r->processor_architecture = PROCESSOR_ARCHITECTURE_INTEL;
3921 r->processor_level = 0x6; /* 6 ???*/
3922 r->ref_ic = 0;
3923 r->reserved2 = 0;
3924 r->reserved3 = 0;
3926 return WERR_OK;
3930 /********************************************************************
3931 * construct_printer_info1
3932 * fill a spoolss_PrinterInfo1 struct
3933 ********************************************************************/
3935 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3936 const struct spoolss_PrinterInfo2 *info2,
3937 uint32_t flags,
3938 const char *servername,
3939 struct spoolss_PrinterInfo1 *r,
3940 int snum)
3942 WERROR result;
3944 r->flags = flags;
3946 if (info2->comment == NULL || info2->comment[0] == '\0') {
3947 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
3948 } else {
3949 r->comment = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3951 W_ERROR_HAVE_NO_MEMORY(r->comment);
3953 result = create_printername(mem_ctx, servername, info2->printername, &r->name);
3954 if (!W_ERROR_IS_OK(result)) {
3955 return result;
3958 r->description = talloc_asprintf(mem_ctx, "%s,%s,%s",
3959 r->name,
3960 info2->drivername,
3961 r->comment);
3962 W_ERROR_HAVE_NO_MEMORY(r->description);
3964 return WERR_OK;
3967 /********************************************************************
3968 * construct_printer_info2
3969 * fill a spoolss_PrinterInfo2 struct
3970 ********************************************************************/
3972 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3973 struct messaging_context *msg_ctx,
3974 const struct spoolss_PrinterInfo2 *info2,
3975 const char *servername,
3976 struct spoolss_PrinterInfo2 *r,
3977 int snum)
3979 int count;
3980 print_status_struct status;
3981 WERROR result;
3983 count = print_queue_length(msg_ctx, snum, &status);
3985 if (servername) {
3986 r->servername = talloc_strdup(mem_ctx, servername);
3987 W_ERROR_HAVE_NO_MEMORY(r->servername);
3988 } else {
3989 r->servername = NULL;
3992 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3993 if (!W_ERROR_IS_OK(result)) {
3994 return result;
3997 r->sharename = talloc_strdup(mem_ctx, lp_servicename(snum));
3998 W_ERROR_HAVE_NO_MEMORY(r->sharename);
3999 r->portname = talloc_strdup(mem_ctx, info2->portname);
4000 W_ERROR_HAVE_NO_MEMORY(r->portname);
4001 r->drivername = talloc_strdup(mem_ctx, info2->drivername);
4002 W_ERROR_HAVE_NO_MEMORY(r->drivername);
4004 if (info2->comment[0] == '\0') {
4005 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
4006 } else {
4007 r->comment = talloc_strdup(mem_ctx, info2->comment);
4009 W_ERROR_HAVE_NO_MEMORY(r->comment);
4011 r->location = talloc_strdup(mem_ctx, info2->location);
4012 if (info2->location[0] == '\0') {
4013 const char *loc = NULL;
4014 NTSTATUS nt_status;
4016 nt_status = printer_list_get_printer(mem_ctx,
4017 info2->sharename,
4018 NULL,
4019 &loc,
4020 NULL);
4021 if (NT_STATUS_IS_OK(nt_status)) {
4022 if (loc != NULL) {
4023 r->location = talloc_strdup(mem_ctx, loc);
4027 W_ERROR_HAVE_NO_MEMORY(r->location);
4029 r->sepfile = talloc_strdup(mem_ctx, info2->sepfile);
4030 W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4031 r->printprocessor = talloc_strdup(mem_ctx, info2->printprocessor);
4032 W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4033 r->datatype = talloc_strdup(mem_ctx, info2->datatype);
4034 W_ERROR_HAVE_NO_MEMORY(r->datatype);
4035 r->parameters = talloc_strdup(mem_ctx, info2->parameters);
4036 W_ERROR_HAVE_NO_MEMORY(r->parameters);
4038 r->attributes = info2->attributes;
4040 r->priority = info2->priority;
4041 r->defaultpriority = info2->defaultpriority;
4042 r->starttime = info2->starttime;
4043 r->untiltime = info2->untiltime;
4044 r->status = nt_printq_status(status.status);
4045 r->cjobs = count;
4046 r->averageppm = info2->averageppm;
4048 copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4049 if (!r->devmode) {
4050 DEBUG(8,("Returning NULL Devicemode!\n"));
4053 compose_devicemode_devicename(r->devmode, r->printername);
4055 r->secdesc = NULL;
4057 if (info2->secdesc != NULL) {
4058 /* don't use talloc_steal() here unless you do a deep steal of all
4059 the SEC_DESC members */
4061 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4064 return WERR_OK;
4067 /********************************************************************
4068 * construct_printer_info3
4069 * fill a spoolss_PrinterInfo3 struct
4070 ********************************************************************/
4072 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4073 const struct spoolss_PrinterInfo2 *info2,
4074 const char *servername,
4075 struct spoolss_PrinterInfo3 *r,
4076 int snum)
4078 /* These are the components of the SD we are returning. */
4080 if (info2->secdesc != NULL) {
4081 /* don't use talloc_steal() here unless you do a deep steal of all
4082 the SEC_DESC members */
4084 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4085 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
4088 return WERR_OK;
4091 /********************************************************************
4092 * construct_printer_info4
4093 * fill a spoolss_PrinterInfo4 struct
4094 ********************************************************************/
4096 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4097 const struct spoolss_PrinterInfo2 *info2,
4098 const char *servername,
4099 struct spoolss_PrinterInfo4 *r,
4100 int snum)
4102 WERROR result;
4104 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4105 if (!W_ERROR_IS_OK(result)) {
4106 return result;
4109 if (servername) {
4110 r->servername = talloc_strdup(mem_ctx, servername);
4111 W_ERROR_HAVE_NO_MEMORY(r->servername);
4112 } else {
4113 r->servername = NULL;
4116 r->attributes = info2->attributes;
4118 return WERR_OK;
4121 /********************************************************************
4122 * construct_printer_info5
4123 * fill a spoolss_PrinterInfo5 struct
4124 ********************************************************************/
4126 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4127 const struct spoolss_PrinterInfo2 *info2,
4128 const char *servername,
4129 struct spoolss_PrinterInfo5 *r,
4130 int snum)
4132 WERROR result;
4134 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4135 if (!W_ERROR_IS_OK(result)) {
4136 return result;
4139 r->portname = talloc_strdup(mem_ctx, info2->portname);
4140 W_ERROR_HAVE_NO_MEMORY(r->portname);
4142 r->attributes = info2->attributes;
4144 /* these two are not used by NT+ according to MSDN */
4145 r->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4146 r->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4148 return WERR_OK;
4151 /********************************************************************
4152 * construct_printer_info_6
4153 * fill a spoolss_PrinterInfo6 struct
4154 ********************************************************************/
4156 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4157 struct messaging_context *msg_ctx,
4158 const struct spoolss_PrinterInfo2 *info2,
4159 const char *servername,
4160 struct spoolss_PrinterInfo6 *r,
4161 int snum)
4163 print_status_struct status;
4165 print_queue_length(msg_ctx, snum, &status);
4167 r->status = nt_printq_status(status.status);
4169 return WERR_OK;
4172 /********************************************************************
4173 * construct_printer_info7
4174 * fill a spoolss_PrinterInfo7 struct
4175 ********************************************************************/
4177 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4178 struct messaging_context *msg_ctx,
4179 const char *servername,
4180 struct spoolss_PrinterInfo7 *r,
4181 int snum)
4183 const struct auth_session_info *session_info = get_session_info_system();
4184 struct GUID guid;
4186 if (is_printer_published(mem_ctx, session_info, msg_ctx,
4187 servername,
4188 lp_servicename(snum), &guid, NULL)) {
4189 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4190 r->action = DSPRINT_PUBLISH;
4191 } else {
4192 r->guid = talloc_strdup(mem_ctx, "");
4193 r->action = DSPRINT_UNPUBLISH;
4195 W_ERROR_HAVE_NO_MEMORY(r->guid);
4197 return WERR_OK;
4200 /********************************************************************
4201 * construct_printer_info8
4202 * fill a spoolss_PrinterInfo8 struct
4203 ********************************************************************/
4205 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4206 const struct spoolss_PrinterInfo2 *info2,
4207 const char *servername,
4208 struct spoolss_DeviceModeInfo *r,
4209 int snum)
4211 WERROR result;
4212 const char *printername;
4214 result = create_printername(mem_ctx, servername, info2->printername, &printername);
4215 if (!W_ERROR_IS_OK(result)) {
4216 return result;
4219 copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4220 if (!r->devmode) {
4221 DEBUG(8,("Returning NULL Devicemode!\n"));
4224 compose_devicemode_devicename(r->devmode, printername);
4226 return WERR_OK;
4230 /********************************************************************
4231 ********************************************************************/
4233 static bool snum_is_shared_printer(int snum)
4235 return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4238 /********************************************************************
4239 Spoolss_enumprinters.
4240 ********************************************************************/
4242 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4243 const struct auth_session_info *session_info,
4244 struct messaging_context *msg_ctx,
4245 const char *servername,
4246 uint32_t level,
4247 uint32_t flags,
4248 union spoolss_PrinterInfo **info_p,
4249 uint32_t *count_p)
4251 int snum;
4252 int n_services = lp_numservices();
4253 union spoolss_PrinterInfo *info = NULL;
4254 uint32_t count = 0;
4255 WERROR result = WERR_OK;
4256 struct dcerpc_binding_handle *b = NULL;
4257 TALLOC_CTX *tmp_ctx = NULL;
4259 tmp_ctx = talloc_new(mem_ctx);
4260 if (!tmp_ctx) {
4261 return WERR_NOMEM;
4264 *count_p = 0;
4265 *info_p = NULL;
4267 for (snum = 0; snum < n_services; snum++) {
4269 const char *printer;
4270 struct spoolss_PrinterInfo2 *info2;
4272 if (!snum_is_shared_printer(snum)) {
4273 continue;
4276 printer = lp_const_servicename(snum);
4278 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4279 printer, snum));
4281 if (b == NULL) {
4282 result = winreg_printer_binding_handle(tmp_ctx,
4283 session_info,
4284 msg_ctx,
4285 &b);
4286 if (!W_ERROR_IS_OK(result)) {
4287 goto out;
4291 result = winreg_create_printer(tmp_ctx, b,
4292 printer);
4293 if (!W_ERROR_IS_OK(result)) {
4294 goto out;
4297 info = talloc_realloc(tmp_ctx, info,
4298 union spoolss_PrinterInfo,
4299 count + 1);
4300 if (!info) {
4301 result = WERR_NOMEM;
4302 goto out;
4305 result = winreg_get_printer(tmp_ctx, b,
4306 printer, &info2);
4307 if (!W_ERROR_IS_OK(result)) {
4308 goto out;
4311 switch (level) {
4312 case 0:
4313 result = construct_printer_info0(info, session_info,
4314 msg_ctx, info2,
4315 servername,
4316 &info[count].info0, snum);
4317 break;
4318 case 1:
4319 result = construct_printer_info1(info, info2, flags,
4320 servername,
4321 &info[count].info1, snum);
4322 break;
4323 case 2:
4324 result = construct_printer_info2(info, msg_ctx, info2,
4325 servername,
4326 &info[count].info2, snum);
4327 break;
4328 case 4:
4329 result = construct_printer_info4(info, info2,
4330 servername,
4331 &info[count].info4, snum);
4332 break;
4333 case 5:
4334 result = construct_printer_info5(info, info2,
4335 servername,
4336 &info[count].info5, snum);
4337 break;
4339 default:
4340 result = WERR_UNKNOWN_LEVEL;
4341 goto out;
4344 if (!W_ERROR_IS_OK(result)) {
4345 goto out;
4348 count++;
4351 out:
4352 if (W_ERROR_IS_OK(result)) {
4353 *info_p = talloc_move(mem_ctx, &info);
4354 *count_p = count;
4357 talloc_free(tmp_ctx);
4359 return result;
4362 /********************************************************************
4363 * handle enumeration of printers at level 0
4364 ********************************************************************/
4366 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4367 const struct auth_session_info *session_info,
4368 struct messaging_context *msg_ctx,
4369 uint32_t flags,
4370 const char *servername,
4371 union spoolss_PrinterInfo **info,
4372 uint32_t *count)
4374 DEBUG(4,("enum_all_printers_info_0\n"));
4376 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4377 servername, 0, flags, info, count);
4381 /********************************************************************
4382 ********************************************************************/
4384 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4385 const struct auth_session_info *session_info,
4386 struct messaging_context *msg_ctx,
4387 const char *servername,
4388 uint32_t flags,
4389 union spoolss_PrinterInfo **info,
4390 uint32_t *count)
4392 DEBUG(4,("enum_all_printers_info_1\n"));
4394 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4395 servername, 1, flags, info, count);
4398 /********************************************************************
4399 enum_all_printers_info_1_local.
4400 *********************************************************************/
4402 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4403 const struct auth_session_info *session_info,
4404 struct messaging_context *msg_ctx,
4405 const char *servername,
4406 union spoolss_PrinterInfo **info,
4407 uint32_t *count)
4409 DEBUG(4,("enum_all_printers_info_1_local\n"));
4411 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4412 servername, PRINTER_ENUM_ICON8, info, count);
4415 /********************************************************************
4416 enum_all_printers_info_1_name.
4417 *********************************************************************/
4419 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4420 const struct auth_session_info *session_info,
4421 struct messaging_context *msg_ctx,
4422 const char *servername,
4423 union spoolss_PrinterInfo **info,
4424 uint32_t *count)
4426 const char *s = servername;
4428 DEBUG(4,("enum_all_printers_info_1_name\n"));
4430 if ((servername[0] == '\\') && (servername[1] == '\\')) {
4431 s = servername + 2;
4434 if (!is_myname_or_ipaddr(s)) {
4435 return WERR_INVALID_NAME;
4438 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4439 servername, PRINTER_ENUM_ICON8, info, count);
4442 /********************************************************************
4443 enum_all_printers_info_1_network.
4444 *********************************************************************/
4446 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4447 const struct auth_session_info *session_info,
4448 struct messaging_context *msg_ctx,
4449 const char *servername,
4450 union spoolss_PrinterInfo **info,
4451 uint32_t *count)
4453 const char *s = servername;
4455 DEBUG(4,("enum_all_printers_info_1_network\n"));
4457 /* If we respond to a enum_printers level 1 on our name with flags
4458 set to PRINTER_ENUM_REMOTE with a list of printers then these
4459 printers incorrectly appear in the APW browse list.
4460 Specifically the printers for the server appear at the workgroup
4461 level where all the other servers in the domain are
4462 listed. Windows responds to this call with a
4463 WERR_CAN_NOT_COMPLETE so we should do the same. */
4465 if (servername[0] == '\\' && servername[1] == '\\') {
4466 s = servername + 2;
4469 if (is_myname_or_ipaddr(s)) {
4470 return WERR_CAN_NOT_COMPLETE;
4473 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4474 servername, PRINTER_ENUM_NAME, info, count);
4477 /********************************************************************
4478 * api_spoolss_enumprinters
4480 * called from api_spoolss_enumprinters (see this to understand)
4481 ********************************************************************/
4483 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4484 const struct auth_session_info *session_info,
4485 struct messaging_context *msg_ctx,
4486 const char *servername,
4487 union spoolss_PrinterInfo **info,
4488 uint32_t *count)
4490 DEBUG(4,("enum_all_printers_info_2\n"));
4492 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4493 servername, 2, 0, info, count);
4496 /********************************************************************
4497 * handle enumeration of printers at level 1
4498 ********************************************************************/
4500 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4501 const struct auth_session_info *session_info,
4502 struct messaging_context *msg_ctx,
4503 uint32_t flags,
4504 const char *servername,
4505 union spoolss_PrinterInfo **info,
4506 uint32_t *count)
4508 /* Not all the flags are equals */
4510 if (flags & PRINTER_ENUM_LOCAL) {
4511 return enum_all_printers_info_1_local(mem_ctx, session_info,
4512 msg_ctx, servername, info, count);
4515 if (flags & PRINTER_ENUM_NAME) {
4516 return enum_all_printers_info_1_name(mem_ctx, session_info,
4517 msg_ctx, servername, info,
4518 count);
4521 if (flags & PRINTER_ENUM_NETWORK) {
4522 return enum_all_printers_info_1_network(mem_ctx, session_info,
4523 msg_ctx, servername, info,
4524 count);
4527 return WERR_OK; /* NT4sp5 does that */
4530 /********************************************************************
4531 * handle enumeration of printers at level 2
4532 ********************************************************************/
4534 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4535 const struct auth_session_info *session_info,
4536 struct messaging_context *msg_ctx,
4537 uint32_t flags,
4538 const char *servername,
4539 union spoolss_PrinterInfo **info,
4540 uint32_t *count)
4542 if (flags & PRINTER_ENUM_LOCAL) {
4544 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4545 servername,
4546 info, count);
4549 if (flags & PRINTER_ENUM_NAME) {
4550 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4551 return WERR_INVALID_NAME;
4554 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4555 servername,
4556 info, count);
4559 if (flags & PRINTER_ENUM_REMOTE) {
4560 return WERR_UNKNOWN_LEVEL;
4563 return WERR_OK;
4566 /********************************************************************
4567 * handle enumeration of printers at level 4
4568 ********************************************************************/
4570 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4571 const struct auth_session_info *session_info,
4572 struct messaging_context *msg_ctx,
4573 uint32_t flags,
4574 const char *servername,
4575 union spoolss_PrinterInfo **info,
4576 uint32_t *count)
4578 DEBUG(4,("enum_all_printers_info_4\n"));
4580 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4581 servername, 4, flags, info, count);
4585 /********************************************************************
4586 * handle enumeration of printers at level 5
4587 ********************************************************************/
4589 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4590 const struct auth_session_info *session_info,
4591 struct messaging_context *msg_ctx,
4592 uint32_t flags,
4593 const char *servername,
4594 union spoolss_PrinterInfo **info,
4595 uint32_t *count)
4597 DEBUG(4,("enum_all_printers_info_5\n"));
4599 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4600 servername, 5, flags, info, count);
4603 /****************************************************************
4604 _spoolss_EnumPrinters
4605 ****************************************************************/
4607 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4608 struct spoolss_EnumPrinters *r)
4610 const struct auth_session_info *session_info = get_session_info_system();
4611 WERROR result;
4613 /* that's an [in out] buffer */
4615 if (!r->in.buffer && (r->in.offered != 0)) {
4616 return WERR_INVALID_PARAM;
4619 DEBUG(4,("_spoolss_EnumPrinters\n"));
4621 *r->out.needed = 0;
4622 *r->out.count = 0;
4623 *r->out.info = NULL;
4626 * Level 1:
4627 * flags==PRINTER_ENUM_NAME
4628 * if name=="" then enumerates all printers
4629 * if name!="" then enumerate the printer
4630 * flags==PRINTER_ENUM_REMOTE
4631 * name is NULL, enumerate printers
4632 * Level 2: name!="" enumerates printers, name can't be NULL
4633 * Level 3: doesn't exist
4634 * Level 4: does a local registry lookup
4635 * Level 5: same as Level 2
4638 if (r->in.server && r->in.server[0] == '\0') {
4639 r->in.server = NULL;
4642 switch (r->in.level) {
4643 case 0:
4644 result = enumprinters_level0(p->mem_ctx, session_info,
4645 p->msg_ctx, r->in.flags,
4646 r->in.server,
4647 r->out.info, r->out.count);
4648 break;
4649 case 1:
4650 result = enumprinters_level1(p->mem_ctx, session_info,
4651 p->msg_ctx, r->in.flags,
4652 r->in.server,
4653 r->out.info, r->out.count);
4654 break;
4655 case 2:
4656 result = enumprinters_level2(p->mem_ctx, session_info,
4657 p->msg_ctx, r->in.flags,
4658 r->in.server,
4659 r->out.info, r->out.count);
4660 break;
4661 case 4:
4662 result = enumprinters_level4(p->mem_ctx, session_info,
4663 p->msg_ctx, r->in.flags,
4664 r->in.server,
4665 r->out.info, r->out.count);
4666 break;
4667 case 5:
4668 result = enumprinters_level5(p->mem_ctx, session_info,
4669 p->msg_ctx, r->in.flags,
4670 r->in.server,
4671 r->out.info, r->out.count);
4672 break;
4673 default:
4674 return WERR_UNKNOWN_LEVEL;
4677 if (!W_ERROR_IS_OK(result)) {
4678 return result;
4681 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4682 spoolss_EnumPrinters,
4683 *r->out.info, r->in.level,
4684 *r->out.count);
4685 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4686 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4688 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4691 /****************************************************************
4692 _spoolss_GetPrinter
4693 ****************************************************************/
4695 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4696 struct spoolss_GetPrinter *r)
4698 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4699 struct spoolss_PrinterInfo2 *info2 = NULL;
4700 WERROR result = WERR_OK;
4701 int snum;
4703 /* that's an [in out] buffer */
4705 if (!r->in.buffer && (r->in.offered != 0)) {
4706 return WERR_INVALID_PARAM;
4709 *r->out.needed = 0;
4711 if (Printer == NULL) {
4712 return WERR_BADFID;
4715 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4716 return WERR_BADFID;
4719 result = winreg_get_printer_internal(p->mem_ctx,
4720 get_session_info_system(),
4721 p->msg_ctx,
4722 lp_const_servicename(snum),
4723 &info2);
4724 if (!W_ERROR_IS_OK(result)) {
4725 goto out;
4728 switch (r->in.level) {
4729 case 0:
4730 result = construct_printer_info0(p->mem_ctx,
4731 get_session_info_system(),
4732 p->msg_ctx,
4733 info2,
4734 Printer->servername,
4735 &r->out.info->info0,
4736 snum);
4737 break;
4738 case 1:
4739 result = construct_printer_info1(p->mem_ctx, info2,
4740 PRINTER_ENUM_ICON8,
4741 Printer->servername,
4742 &r->out.info->info1, snum);
4743 break;
4744 case 2:
4745 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4746 Printer->servername,
4747 &r->out.info->info2, snum);
4748 break;
4749 case 3:
4750 result = construct_printer_info3(p->mem_ctx, info2,
4751 Printer->servername,
4752 &r->out.info->info3, snum);
4753 break;
4754 case 4:
4755 result = construct_printer_info4(p->mem_ctx, info2,
4756 Printer->servername,
4757 &r->out.info->info4, snum);
4758 break;
4759 case 5:
4760 result = construct_printer_info5(p->mem_ctx, info2,
4761 Printer->servername,
4762 &r->out.info->info5, snum);
4763 break;
4764 case 6:
4765 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4766 Printer->servername,
4767 &r->out.info->info6, snum);
4768 break;
4769 case 7:
4770 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4771 Printer->servername,
4772 &r->out.info->info7, snum);
4773 break;
4774 case 8:
4775 result = construct_printer_info8(p->mem_ctx, info2,
4776 Printer->servername,
4777 &r->out.info->info8, snum);
4778 break;
4779 default:
4780 result = WERR_UNKNOWN_LEVEL;
4781 break;
4783 TALLOC_FREE(info2);
4785 out:
4786 if (!W_ERROR_IS_OK(result)) {
4787 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4788 r->in.level, win_errstr(result)));
4789 TALLOC_FREE(r->out.info);
4790 return result;
4793 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4794 r->out.info, r->in.level);
4795 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4797 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4800 /********************************************************************
4801 ********************************************************************/
4803 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4804 do { \
4805 if (in && strlen(in)) { \
4806 out = talloc_strdup(mem_ctx, in); \
4807 } else { \
4808 out = talloc_strdup(mem_ctx, ""); \
4810 W_ERROR_HAVE_NO_MEMORY(out); \
4811 } while (0);
4813 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4814 do { \
4815 if (in && strlen(in)) { \
4816 out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4817 } else { \
4818 out = talloc_strdup(mem_ctx, ""); \
4820 W_ERROR_HAVE_NO_MEMORY(out); \
4821 } while (0);
4823 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4824 const char **string_array,
4825 const char ***presult,
4826 const char *cservername,
4827 const char *arch,
4828 int version)
4830 int i, num_strings = 0;
4831 const char **array = NULL;
4833 if (string_array == NULL) {
4834 return WERR_INVALID_PARAMETER;
4837 for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4838 const char *str = NULL;
4840 if (cservername == NULL || arch == NULL) {
4841 FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4842 } else {
4843 FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4846 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4847 TALLOC_FREE(array);
4848 return WERR_NOMEM;
4852 if (i > 0) {
4853 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4854 &array, &num_strings);
4857 if (presult) {
4858 *presult = array;
4861 return WERR_OK;
4864 /********************************************************************
4865 * fill a spoolss_DriverInfo1 struct
4866 ********************************************************************/
4868 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4869 struct spoolss_DriverInfo1 *r,
4870 const struct spoolss_DriverInfo8 *driver,
4871 const char *servername)
4873 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4874 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4876 return WERR_OK;
4879 /********************************************************************
4880 * fill a spoolss_DriverInfo2 struct
4881 ********************************************************************/
4883 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4884 struct spoolss_DriverInfo2 *r,
4885 const struct spoolss_DriverInfo8 *driver,
4886 const char *servername)
4889 const char *cservername = canon_servername(servername);
4891 r->version = driver->version;
4893 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4894 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4895 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4896 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4898 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4899 driver->architecture,
4900 driver->version,
4901 driver->driver_path,
4902 r->driver_path);
4904 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4905 driver->architecture,
4906 driver->version,
4907 driver->data_file,
4908 r->data_file);
4910 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4911 driver->architecture,
4912 driver->version,
4913 driver->config_file,
4914 r->config_file);
4916 return WERR_OK;
4919 /********************************************************************
4920 * fill a spoolss_DriverInfo3 struct
4921 ********************************************************************/
4923 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4924 struct spoolss_DriverInfo3 *r,
4925 const struct spoolss_DriverInfo8 *driver,
4926 const char *servername)
4928 const char *cservername = canon_servername(servername);
4930 r->version = driver->version;
4932 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4933 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4934 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4935 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4937 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4938 driver->architecture,
4939 driver->version,
4940 driver->driver_path,
4941 r->driver_path);
4943 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4944 driver->architecture,
4945 driver->version,
4946 driver->data_file,
4947 r->data_file);
4949 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4950 driver->architecture,
4951 driver->version,
4952 driver->config_file,
4953 r->config_file);
4955 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4956 driver->architecture,
4957 driver->version,
4958 driver->help_file,
4959 r->help_file);
4961 FILL_DRIVER_STRING(mem_ctx,
4962 driver->monitor_name,
4963 r->monitor_name);
4965 FILL_DRIVER_STRING(mem_ctx,
4966 driver->default_datatype,
4967 r->default_datatype);
4969 return string_array_from_driver_info(mem_ctx,
4970 driver->dependent_files,
4971 &r->dependent_files,
4972 cservername,
4973 driver->architecture,
4974 driver->version);
4977 /********************************************************************
4978 * fill a spoolss_DriverInfo4 struct
4979 ********************************************************************/
4981 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4982 struct spoolss_DriverInfo4 *r,
4983 const struct spoolss_DriverInfo8 *driver,
4984 const char *servername)
4986 const char *cservername = canon_servername(servername);
4987 WERROR result;
4989 r->version = driver->version;
4991 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4992 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4993 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4994 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4996 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4997 driver->architecture,
4998 driver->version,
4999 driver->driver_path,
5000 r->driver_path);
5002 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5003 driver->architecture,
5004 driver->version,
5005 driver->data_file,
5006 r->data_file);
5008 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5009 driver->architecture,
5010 driver->version,
5011 driver->config_file,
5012 r->config_file);
5014 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5015 driver->architecture,
5016 driver->version,
5017 driver->help_file,
5018 r->help_file);
5020 result = string_array_from_driver_info(mem_ctx,
5021 driver->dependent_files,
5022 &r->dependent_files,
5023 cservername,
5024 driver->architecture,
5025 driver->version);
5026 if (!W_ERROR_IS_OK(result)) {
5027 return result;
5030 FILL_DRIVER_STRING(mem_ctx,
5031 driver->monitor_name,
5032 r->monitor_name);
5034 FILL_DRIVER_STRING(mem_ctx,
5035 driver->default_datatype,
5036 r->default_datatype);
5039 result = string_array_from_driver_info(mem_ctx,
5040 driver->previous_names,
5041 &r->previous_names,
5042 NULL, NULL, 0);
5044 return result;
5047 /********************************************************************
5048 * fill a spoolss_DriverInfo5 struct
5049 ********************************************************************/
5051 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5052 struct spoolss_DriverInfo5 *r,
5053 const struct spoolss_DriverInfo8 *driver,
5054 const char *servername)
5056 const char *cservername = canon_servername(servername);
5058 r->version = driver->version;
5060 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5061 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5062 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5063 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5065 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5066 driver->architecture,
5067 driver->version,
5068 driver->driver_path,
5069 r->driver_path);
5071 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5072 driver->architecture,
5073 driver->version,
5074 driver->data_file,
5075 r->data_file);
5077 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5078 driver->architecture,
5079 driver->version,
5080 driver->config_file,
5081 r->config_file);
5083 r->driver_attributes = 0;
5084 r->config_version = 0;
5085 r->driver_version = 0;
5087 return WERR_OK;
5089 /********************************************************************
5090 * fill a spoolss_DriverInfo6 struct
5091 ********************************************************************/
5093 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5094 struct spoolss_DriverInfo6 *r,
5095 const struct spoolss_DriverInfo8 *driver,
5096 const char *servername)
5098 const char *cservername = canon_servername(servername);
5099 WERROR result;
5101 r->version = driver->version;
5103 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5104 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5105 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5106 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5108 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5109 driver->architecture,
5110 driver->version,
5111 driver->driver_path,
5112 r->driver_path);
5114 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5115 driver->architecture,
5116 driver->version,
5117 driver->data_file,
5118 r->data_file);
5120 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5121 driver->architecture,
5122 driver->version,
5123 driver->config_file,
5124 r->config_file);
5126 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5127 driver->architecture,
5128 driver->version,
5129 driver->help_file,
5130 r->help_file);
5132 FILL_DRIVER_STRING(mem_ctx,
5133 driver->monitor_name,
5134 r->monitor_name);
5136 FILL_DRIVER_STRING(mem_ctx,
5137 driver->default_datatype,
5138 r->default_datatype);
5140 result = string_array_from_driver_info(mem_ctx,
5141 driver->dependent_files,
5142 &r->dependent_files,
5143 cservername,
5144 driver->architecture,
5145 driver->version);
5146 if (!W_ERROR_IS_OK(result)) {
5147 return result;
5150 result = string_array_from_driver_info(mem_ctx,
5151 driver->previous_names,
5152 &r->previous_names,
5153 NULL, NULL, 0);
5154 if (!W_ERROR_IS_OK(result)) {
5155 return result;
5158 r->driver_date = driver->driver_date;
5159 r->driver_version = driver->driver_version;
5161 FILL_DRIVER_STRING(mem_ctx,
5162 driver->manufacturer_name,
5163 r->manufacturer_name);
5164 FILL_DRIVER_STRING(mem_ctx,
5165 driver->manufacturer_url,
5166 r->manufacturer_url);
5167 FILL_DRIVER_STRING(mem_ctx,
5168 driver->hardware_id,
5169 r->hardware_id);
5170 FILL_DRIVER_STRING(mem_ctx,
5171 driver->provider,
5172 r->provider);
5174 return WERR_OK;
5177 /********************************************************************
5178 * fill a spoolss_DriverInfo8 struct
5179 ********************************************************************/
5181 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5182 struct spoolss_DriverInfo8 *r,
5183 const struct spoolss_DriverInfo8 *driver,
5184 const char *servername)
5186 const char *cservername = canon_servername(servername);
5187 WERROR result;
5189 r->version = driver->version;
5191 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5192 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5193 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5194 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5196 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5197 driver->architecture,
5198 driver->version,
5199 driver->driver_path,
5200 r->driver_path);
5202 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5203 driver->architecture,
5204 driver->version,
5205 driver->data_file,
5206 r->data_file);
5208 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5209 driver->architecture,
5210 driver->version,
5211 driver->config_file,
5212 r->config_file);
5214 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5215 driver->architecture,
5216 driver->version,
5217 driver->help_file,
5218 r->help_file);
5220 FILL_DRIVER_STRING(mem_ctx,
5221 driver->monitor_name,
5222 r->monitor_name);
5224 FILL_DRIVER_STRING(mem_ctx,
5225 driver->default_datatype,
5226 r->default_datatype);
5228 result = string_array_from_driver_info(mem_ctx,
5229 driver->dependent_files,
5230 &r->dependent_files,
5231 cservername,
5232 driver->architecture,
5233 driver->version);
5234 if (!W_ERROR_IS_OK(result)) {
5235 return result;
5238 result = string_array_from_driver_info(mem_ctx,
5239 driver->previous_names,
5240 &r->previous_names,
5241 NULL, NULL, 0);
5242 if (!W_ERROR_IS_OK(result)) {
5243 return result;
5246 r->driver_date = driver->driver_date;
5247 r->driver_version = driver->driver_version;
5249 FILL_DRIVER_STRING(mem_ctx,
5250 driver->manufacturer_name,
5251 r->manufacturer_name);
5252 FILL_DRIVER_STRING(mem_ctx,
5253 driver->manufacturer_url,
5254 r->manufacturer_url);
5255 FILL_DRIVER_STRING(mem_ctx,
5256 driver->hardware_id,
5257 r->hardware_id);
5258 FILL_DRIVER_STRING(mem_ctx,
5259 driver->provider,
5260 r->provider);
5262 FILL_DRIVER_STRING(mem_ctx,
5263 driver->print_processor,
5264 r->print_processor);
5265 FILL_DRIVER_STRING(mem_ctx,
5266 driver->vendor_setup,
5267 r->vendor_setup);
5269 result = string_array_from_driver_info(mem_ctx,
5270 driver->color_profiles,
5271 &r->color_profiles,
5272 NULL, NULL, 0);
5273 if (!W_ERROR_IS_OK(result)) {
5274 return result;
5277 FILL_DRIVER_STRING(mem_ctx,
5278 driver->inf_path,
5279 r->inf_path);
5281 r->printer_driver_attributes = driver->printer_driver_attributes;
5283 result = string_array_from_driver_info(mem_ctx,
5284 driver->core_driver_dependencies,
5285 &r->core_driver_dependencies,
5286 NULL, NULL, 0);
5287 if (!W_ERROR_IS_OK(result)) {
5288 return result;
5291 r->min_inbox_driver_ver_date = driver->min_inbox_driver_ver_date;
5292 r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5294 return WERR_OK;
5297 #if 0 /* disabled until marshalling issues are resolved - gd */
5298 /********************************************************************
5299 ********************************************************************/
5301 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5302 struct spoolss_DriverFileInfo *r,
5303 const char *cservername,
5304 const char *file_name,
5305 enum spoolss_DriverFileType file_type,
5306 uint32_t file_version)
5308 r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
5309 cservername, file_name);
5310 W_ERROR_HAVE_NO_MEMORY(r->file_name);
5311 r->file_type = file_type;
5312 r->file_version = file_version;
5314 return WERR_OK;
5317 /********************************************************************
5318 ********************************************************************/
5320 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5321 const struct spoolss_DriverInfo8 *driver,
5322 const char *cservername,
5323 struct spoolss_DriverFileInfo **info_p,
5324 uint32_t *count_p)
5326 struct spoolss_DriverFileInfo *info = NULL;
5327 uint32_t count = 0;
5328 WERROR result;
5329 uint32_t i;
5331 *info_p = NULL;
5332 *count_p = 0;
5334 if (strlen(driver->driver_path)) {
5335 info = talloc_realloc(mem_ctx, info,
5336 struct spoolss_DriverFileInfo,
5337 count + 1);
5338 W_ERROR_HAVE_NO_MEMORY(info);
5339 result = fill_spoolss_DriverFileInfo(info,
5340 &info[count],
5341 cservername,
5342 driver->driver_path,
5343 SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5345 W_ERROR_NOT_OK_RETURN(result);
5346 count++;
5349 if (strlen(driver->config_file)) {
5350 info = talloc_realloc(mem_ctx, info,
5351 struct spoolss_DriverFileInfo,
5352 count + 1);
5353 W_ERROR_HAVE_NO_MEMORY(info);
5354 result = fill_spoolss_DriverFileInfo(info,
5355 &info[count],
5356 cservername,
5357 driver->config_file,
5358 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5360 W_ERROR_NOT_OK_RETURN(result);
5361 count++;
5364 if (strlen(driver->data_file)) {
5365 info = talloc_realloc(mem_ctx, info,
5366 struct spoolss_DriverFileInfo,
5367 count + 1);
5368 W_ERROR_HAVE_NO_MEMORY(info);
5369 result = fill_spoolss_DriverFileInfo(info,
5370 &info[count],
5371 cservername,
5372 driver->data_file,
5373 SPOOLSS_DRIVER_FILE_TYPE_DATA,
5375 W_ERROR_NOT_OK_RETURN(result);
5376 count++;
5379 if (strlen(driver->help_file)) {
5380 info = talloc_realloc(mem_ctx, info,
5381 struct spoolss_DriverFileInfo,
5382 count + 1);
5383 W_ERROR_HAVE_NO_MEMORY(info);
5384 result = fill_spoolss_DriverFileInfo(info,
5385 &info[count],
5386 cservername,
5387 driver->help_file,
5388 SPOOLSS_DRIVER_FILE_TYPE_HELP,
5390 W_ERROR_NOT_OK_RETURN(result);
5391 count++;
5394 for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5395 info = talloc_realloc(mem_ctx, info,
5396 struct spoolss_DriverFileInfo,
5397 count + 1);
5398 W_ERROR_HAVE_NO_MEMORY(info);
5399 result = fill_spoolss_DriverFileInfo(info,
5400 &info[count],
5401 cservername,
5402 driver->dependent_files[i],
5403 SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5405 W_ERROR_NOT_OK_RETURN(result);
5406 count++;
5409 *info_p = info;
5410 *count_p = count;
5412 return WERR_OK;
5415 /********************************************************************
5416 * fill a spoolss_DriverInfo101 struct
5417 ********************************************************************/
5419 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5420 struct spoolss_DriverInfo101 *r,
5421 const struct spoolss_DriverInfo8 *driver,
5422 const char *servername)
5424 const char *cservername = canon_servername(servername);
5425 WERROR result;
5427 r->version = driver->version;
5429 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5430 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5431 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5432 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5434 result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5435 cservername,
5436 &r->file_info,
5437 &r->file_count);
5438 if (!W_ERROR_IS_OK(result)) {
5439 return result;
5442 FILL_DRIVER_STRING(mem_ctx,
5443 driver->monitor_name,
5444 r->monitor_name);
5446 FILL_DRIVER_STRING(mem_ctx,
5447 driver->default_datatype,
5448 r->default_datatype);
5450 result = string_array_from_driver_info(mem_ctx,
5451 driver->previous_names,
5452 &r->previous_names,
5453 NULL, NULL, 0);
5454 if (!W_ERROR_IS_OK(result)) {
5455 return result;
5458 r->driver_date = driver->driver_date;
5459 r->driver_version = driver->driver_version;
5461 FILL_DRIVER_STRING(mem_ctx,
5462 driver->manufacturer_name,
5463 r->manufacturer_name);
5464 FILL_DRIVER_STRING(mem_ctx,
5465 driver->manufacturer_url,
5466 r->manufacturer_url);
5467 FILL_DRIVER_STRING(mem_ctx,
5468 driver->hardware_id,
5469 r->hardware_id);
5470 FILL_DRIVER_STRING(mem_ctx,
5471 driver->provider,
5472 r->provider);
5474 return WERR_OK;
5476 #endif
5477 /********************************************************************
5478 ********************************************************************/
5480 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5481 const struct auth_session_info *session_info,
5482 struct messaging_context *msg_ctx,
5483 uint32_t level,
5484 union spoolss_DriverInfo *r,
5485 int snum,
5486 const char *servername,
5487 const char *architecture,
5488 uint32_t version)
5490 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5491 struct spoolss_DriverInfo8 *driver;
5492 WERROR result;
5493 struct dcerpc_binding_handle *b;
5494 TALLOC_CTX *tmp_ctx = NULL;
5496 if (level == 101) {
5497 return WERR_UNKNOWN_LEVEL;
5500 tmp_ctx = talloc_new(mem_ctx);
5501 if (!tmp_ctx) {
5502 return WERR_NOMEM;
5505 result = winreg_printer_binding_handle(tmp_ctx,
5506 session_info,
5507 msg_ctx,
5508 &b);
5509 if (!W_ERROR_IS_OK(result)) {
5510 goto done;
5513 result = winreg_get_printer(tmp_ctx, b,
5514 lp_const_servicename(snum),
5515 &pinfo2);
5517 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5518 win_errstr(result)));
5520 if (!W_ERROR_IS_OK(result)) {
5521 result = WERR_INVALID_PRINTER_NAME;
5522 goto done;
5525 result = winreg_get_driver(tmp_ctx, b,
5526 architecture,
5527 pinfo2->drivername, version, &driver);
5529 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5530 win_errstr(result)));
5532 if (!W_ERROR_IS_OK(result)) {
5534 * Is this a W2k client ?
5537 if (version < 3) {
5538 result = WERR_UNKNOWN_PRINTER_DRIVER;
5539 goto done;
5542 /* Yes - try again with a WinNT driver. */
5543 version = 2;
5544 result = winreg_get_driver(tmp_ctx, b,
5545 architecture,
5546 pinfo2->drivername,
5547 version, &driver);
5548 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5549 win_errstr(result)));
5550 if (!W_ERROR_IS_OK(result)) {
5551 result = WERR_UNKNOWN_PRINTER_DRIVER;
5552 goto done;
5556 /* these are allocated on mem_ctx and not tmp_ctx because they are
5557 * the 'return value' and need to utlive this call */
5558 switch (level) {
5559 case 1:
5560 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5561 break;
5562 case 2:
5563 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5564 break;
5565 case 3:
5566 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5567 break;
5568 case 4:
5569 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5570 break;
5571 case 5:
5572 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5573 break;
5574 case 6:
5575 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5576 break;
5577 case 8:
5578 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5579 break;
5580 #if 0 /* disabled until marshalling issues are resolved - gd */
5581 case 101:
5582 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5583 break;
5584 #endif
5585 default:
5586 result = WERR_UNKNOWN_LEVEL;
5587 break;
5590 done:
5591 talloc_free(tmp_ctx);
5592 return result;
5595 /****************************************************************
5596 _spoolss_GetPrinterDriver2
5597 ****************************************************************/
5599 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5600 struct spoolss_GetPrinterDriver2 *r)
5602 struct printer_handle *printer;
5603 WERROR result;
5605 int snum;
5607 /* that's an [in out] buffer */
5609 if (!r->in.buffer && (r->in.offered != 0)) {
5610 return WERR_INVALID_PARAM;
5613 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5615 if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5616 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5617 return WERR_INVALID_PRINTER_NAME;
5620 *r->out.needed = 0;
5621 *r->out.server_major_version = 0;
5622 *r->out.server_minor_version = 0;
5624 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5625 return WERR_BADFID;
5628 result = construct_printer_driver_info_level(p->mem_ctx,
5629 get_session_info_system(),
5630 p->msg_ctx,
5631 r->in.level, r->out.info,
5632 snum, printer->servername,
5633 r->in.architecture,
5634 r->in.client_major_version);
5635 if (!W_ERROR_IS_OK(result)) {
5636 TALLOC_FREE(r->out.info);
5637 return result;
5640 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5641 r->out.info, r->in.level);
5642 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5644 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5648 /****************************************************************
5649 _spoolss_StartPagePrinter
5650 ****************************************************************/
5652 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5653 struct spoolss_StartPagePrinter *r)
5655 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5657 if (!Printer) {
5658 DEBUG(3,("_spoolss_StartPagePrinter: "
5659 "Error in startpageprinter printer handle\n"));
5660 return WERR_BADFID;
5663 Printer->page_started = true;
5664 return WERR_OK;
5667 /****************************************************************
5668 _spoolss_EndPagePrinter
5669 ****************************************************************/
5671 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5672 struct spoolss_EndPagePrinter *r)
5674 int snum;
5676 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5678 if (!Printer) {
5679 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5680 OUR_HANDLE(r->in.handle)));
5681 return WERR_BADFID;
5684 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5685 return WERR_BADFID;
5687 Printer->page_started = false;
5688 print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5690 return WERR_OK;
5693 /****************************************************************
5694 _spoolss_StartDocPrinter
5695 ****************************************************************/
5697 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5698 struct spoolss_StartDocPrinter *r)
5700 struct spoolss_DocumentInfo1 *info_1;
5701 int snum;
5702 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5703 WERROR werr;
5704 char *rhost;
5705 int rc;
5707 if (!Printer) {
5708 DEBUG(2,("_spoolss_StartDocPrinter: "
5709 "Invalid handle (%s:%u:%u)\n",
5710 OUR_HANDLE(r->in.handle)));
5711 return WERR_BADFID;
5714 if (Printer->jobid) {
5715 DEBUG(2, ("_spoolss_StartDocPrinter: "
5716 "StartDocPrinter called twice! "
5717 "(existing jobid = %d)\n", Printer->jobid));
5718 return WERR_INVALID_HANDLE;
5721 if (r->in.level != 1) {
5722 return WERR_UNKNOWN_LEVEL;
5725 info_1 = r->in.info.info1;
5728 * a nice thing with NT is it doesn't listen to what you tell it.
5729 * when asked to send _only_ RAW datas, it tries to send datas
5730 * in EMF format.
5732 * So I add checks like in NT Server ...
5735 if (info_1->datatype) {
5736 if (strcmp(info_1->datatype, "RAW") != 0) {
5737 *r->out.job_id = 0;
5738 return WERR_INVALID_DATATYPE;
5742 /* get the share number of the printer */
5743 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5744 return WERR_BADFID;
5747 rc = get_remote_hostname(p->remote_address,
5748 &rhost,
5749 p->mem_ctx);
5750 if (rc < 0) {
5751 return WERR_NOMEM;
5753 if (strequal(rhost,"UNKNOWN")) {
5754 rhost = tsocket_address_inet_addr_string(p->remote_address,
5755 p->mem_ctx);
5756 if (rhost == NULL) {
5757 return WERR_NOMEM;
5761 werr = print_job_start(p->session_info,
5762 p->msg_ctx,
5763 rhost,
5764 snum,
5765 info_1->document_name,
5766 info_1->output_file,
5767 Printer->devmode,
5768 &Printer->jobid);
5770 /* An error occured in print_job_start() so return an appropriate
5771 NT error code. */
5773 if (!W_ERROR_IS_OK(werr)) {
5774 return werr;
5777 Printer->document_started = true;
5778 *r->out.job_id = Printer->jobid;
5780 return WERR_OK;
5783 /****************************************************************
5784 _spoolss_EndDocPrinter
5785 ****************************************************************/
5787 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5788 struct spoolss_EndDocPrinter *r)
5790 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5791 NTSTATUS status;
5792 int snum;
5794 if (!Printer) {
5795 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5796 OUR_HANDLE(r->in.handle)));
5797 return WERR_BADFID;
5800 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5801 return WERR_BADFID;
5804 Printer->document_started = false;
5805 status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5806 if (!NT_STATUS_IS_OK(status)) {
5807 DEBUG(2, ("_spoolss_EndDocPrinter: "
5808 "print_job_end failed [%s]\n",
5809 nt_errstr(status)));
5812 Printer->jobid = 0;
5813 return ntstatus_to_werror(status);
5816 /****************************************************************
5817 _spoolss_WritePrinter
5818 ****************************************************************/
5820 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5821 struct spoolss_WritePrinter *r)
5823 ssize_t buffer_written;
5824 int snum;
5825 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5827 if (!Printer) {
5828 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5829 OUR_HANDLE(r->in.handle)));
5830 *r->out.num_written = r->in._data_size;
5831 return WERR_BADFID;
5834 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5835 return WERR_BADFID;
5837 /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5838 buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5839 snum, Printer->jobid,
5840 (const char *)r->in.data.data,
5841 (size_t)r->in._data_size);
5842 if (buffer_written == (ssize_t)-1) {
5843 *r->out.num_written = 0;
5844 if (errno == ENOSPC)
5845 return WERR_NO_SPOOL_SPACE;
5846 else
5847 return WERR_ACCESS_DENIED;
5850 *r->out.num_written = r->in._data_size;
5852 return WERR_OK;
5855 /********************************************************************
5856 * api_spoolss_getprinter
5857 * called from the spoolss dispatcher
5859 ********************************************************************/
5861 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5862 struct pipes_struct *p)
5864 const struct auth_session_info *session_info = p->session_info;
5865 int snum;
5866 WERROR errcode = WERR_BADFUNC;
5867 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5869 if (!Printer) {
5870 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5871 OUR_HANDLE(handle)));
5872 return WERR_BADFID;
5875 if (!get_printer_snum(p, handle, &snum, NULL))
5876 return WERR_BADFID;
5878 switch (command) {
5879 case SPOOLSS_PRINTER_CONTROL_PAUSE:
5880 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
5881 break;
5882 case SPOOLSS_PRINTER_CONTROL_RESUME:
5883 case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5884 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
5885 break;
5886 case SPOOLSS_PRINTER_CONTROL_PURGE:
5887 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
5888 break;
5889 default:
5890 return WERR_UNKNOWN_LEVEL;
5893 return errcode;
5897 /****************************************************************
5898 _spoolss_AbortPrinter
5899 * From MSDN: "Deletes printer's spool file if printer is configured
5900 * for spooling"
5901 ****************************************************************/
5903 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
5904 struct spoolss_AbortPrinter *r)
5906 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5907 int snum;
5908 WERROR errcode = WERR_OK;
5910 if (!Printer) {
5911 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5912 OUR_HANDLE(r->in.handle)));
5913 return WERR_BADFID;
5916 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5917 return WERR_BADFID;
5919 if (!Printer->document_started) {
5920 return WERR_SPL_NO_STARTDOC;
5923 errcode = print_job_delete(p->session_info,
5924 p->msg_ctx,
5925 snum,
5926 Printer->jobid);
5928 return errcode;
5931 /********************************************************************
5932 * called by spoolss_api_setprinter
5933 * when updating a printer description
5934 ********************************************************************/
5936 static WERROR update_printer_sec(struct policy_handle *handle,
5937 struct pipes_struct *p,
5938 struct sec_desc_buf *secdesc_ctr)
5940 struct spoolss_security_descriptor *new_secdesc = NULL;
5941 struct spoolss_security_descriptor *old_secdesc = NULL;
5942 const char *printer;
5943 WERROR result;
5944 int snum;
5945 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5946 struct dcerpc_binding_handle *b;
5947 TALLOC_CTX *tmp_ctx = NULL;
5949 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5950 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5951 OUR_HANDLE(handle)));
5953 result = WERR_BADFID;
5954 goto done;
5957 if (secdesc_ctr == NULL) {
5958 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5959 result = WERR_INVALID_PARAM;
5960 goto done;
5962 printer = lp_const_servicename(snum);
5964 /* Check the user has permissions to change the security
5965 descriptor. By experimentation with two NT machines, the user
5966 requires Full Access to the printer to change security
5967 information. */
5969 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5970 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5971 result = WERR_ACCESS_DENIED;
5972 goto done;
5975 tmp_ctx = talloc_new(p->mem_ctx);
5976 if (!tmp_ctx) {
5977 return WERR_NOMEM;
5980 result = winreg_printer_binding_handle(tmp_ctx,
5981 get_session_info_system(),
5982 p->msg_ctx,
5983 &b);
5984 if (!W_ERROR_IS_OK(result)) {
5985 goto done;
5988 /* NT seems to like setting the security descriptor even though
5989 nothing may have actually changed. */
5990 result = winreg_get_printer_secdesc(tmp_ctx, b,
5991 printer,
5992 &old_secdesc);
5993 if (!W_ERROR_IS_OK(result)) {
5994 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
5995 result = WERR_BADFID;
5996 goto done;
5999 if (DEBUGLEVEL >= 10) {
6000 struct security_acl *the_acl;
6001 int i;
6003 the_acl = old_secdesc->dacl;
6004 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6005 printer, the_acl->num_aces));
6007 for (i = 0; i < the_acl->num_aces; i++) {
6008 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6009 &the_acl->aces[i].trustee),
6010 the_acl->aces[i].access_mask));
6013 the_acl = secdesc_ctr->sd->dacl;
6015 if (the_acl) {
6016 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6017 printer, the_acl->num_aces));
6019 for (i = 0; i < the_acl->num_aces; i++) {
6020 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6021 &the_acl->aces[i].trustee),
6022 the_acl->aces[i].access_mask));
6024 } else {
6025 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6029 new_secdesc = sec_desc_merge(tmp_ctx, secdesc_ctr->sd, old_secdesc);
6030 if (new_secdesc == NULL) {
6031 result = WERR_NOMEM;
6032 goto done;
6035 if (security_descriptor_equal(new_secdesc, old_secdesc)) {
6036 result = WERR_OK;
6037 goto done;
6040 result = winreg_set_printer_secdesc(tmp_ctx, b,
6041 printer,
6042 new_secdesc);
6044 done:
6045 talloc_free(tmp_ctx);
6046 return result;
6049 /********************************************************************
6050 Canonicalize printer info from a client
6051 ********************************************************************/
6053 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
6054 struct spoolss_SetPrinterInfo2 *info2,
6055 int snum)
6057 fstring printername;
6058 const char *p;
6060 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6061 "portname=%s drivername=%s comment=%s location=%s\n",
6062 info2->servername, info2->printername, info2->sharename,
6063 info2->portname, info2->drivername, info2->comment,
6064 info2->location));
6066 /* we force some elements to "correct" values */
6067 info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
6068 if (info2->servername == NULL) {
6069 return false;
6071 info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6072 if (info2->sharename == NULL) {
6073 return false;
6076 /* check to see if we allow printername != sharename */
6077 if (lp_force_printername(snum)) {
6078 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6079 lp_netbios_name(), info2->sharename);
6080 } else {
6081 /* make sure printername is in \\server\printername format */
6082 fstrcpy(printername, info2->printername);
6083 p = printername;
6084 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6085 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6086 p++;
6089 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6090 lp_netbios_name(), p);
6092 if (info2->printername == NULL) {
6093 return false;
6096 info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6097 info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6099 return true;
6102 /****************************************************************************
6103 ****************************************************************************/
6105 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6107 char *cmd = lp_addport_cmd();
6108 char *command = NULL;
6109 int ret;
6110 bool is_print_op = false;
6112 if ( !*cmd ) {
6113 return WERR_ACCESS_DENIED;
6116 command = talloc_asprintf(ctx,
6117 "%s \"%s\" \"%s\"", cmd, portname, uri );
6118 if (!command) {
6119 return WERR_NOMEM;
6122 if ( token )
6123 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6125 DEBUG(10,("Running [%s]\n", command));
6127 /********* BEGIN SePrintOperatorPrivilege **********/
6129 if ( is_print_op )
6130 become_root();
6132 ret = smbrun(command, 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 return WERR_ACCESS_DENIED;
6147 return WERR_OK;
6150 /****************************************************************************
6151 ****************************************************************************/
6153 static bool spoolss_conn_snum_used(struct smbd_server_connection *sconn,
6154 int snum)
6157 * As we do not know if we are embedded in the file server process
6158 * or not, we have to pretend that all shares are in use.
6160 return true;
6163 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6164 struct spoolss_SetPrinterInfo2 *info2,
6165 const char *remote_machine,
6166 struct messaging_context *msg_ctx)
6168 char *cmd = lp_addprinter_cmd();
6169 char **qlines;
6170 char *command = NULL;
6171 int numlines;
6172 int ret;
6173 int fd;
6174 bool is_print_op = false;
6176 if (!remote_machine) {
6177 return false;
6180 command = talloc_asprintf(ctx,
6181 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6182 cmd, info2->printername, info2->sharename,
6183 info2->portname, info2->drivername,
6184 info2->location, info2->comment, remote_machine);
6185 if (!command) {
6186 return false;
6189 if ( token )
6190 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6192 DEBUG(10,("Running [%s]\n", command));
6194 /********* BEGIN SePrintOperatorPrivilege **********/
6196 if ( is_print_op )
6197 become_root();
6199 if ( (ret = smbrun(command, &fd)) == 0 ) {
6200 /* Tell everyone we updated smb.conf. */
6201 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6204 if ( is_print_op )
6205 unbecome_root();
6207 /********* END SePrintOperatorPrivilege **********/
6209 DEBUGADD(10,("returned [%d]\n", ret));
6211 TALLOC_FREE(command);
6213 if ( ret != 0 ) {
6214 if (fd != -1)
6215 close(fd);
6216 return false;
6219 /* reload our services immediately */
6220 become_root();
6221 reload_services(NULL, spoolss_conn_snum_used, false);
6222 unbecome_root();
6224 numlines = 0;
6225 /* Get lines and convert them back to dos-codepage */
6226 qlines = fd_lines_load(fd, &numlines, 0, NULL);
6227 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6228 close(fd);
6230 /* Set the portname to what the script says the portname should be. */
6231 /* but don't require anything to be return from the script exit a good error code */
6233 if (numlines) {
6234 /* Set the portname to what the script says the portname should be. */
6235 info2->portname = talloc_strdup(ctx, qlines[0]);
6236 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6239 TALLOC_FREE(qlines);
6240 return true;
6243 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6244 const struct auth_session_info *session_info,
6245 struct messaging_context *msg_ctx,
6246 int snum,
6247 struct spoolss_SetPrinterInfo2 *printer,
6248 struct spoolss_PrinterInfo2 *old_printer)
6250 bool force_update = (old_printer == NULL);
6251 const char *dnsdomname;
6252 const char *longname;
6253 const char *uncname;
6254 const char *spooling;
6255 DATA_BLOB buffer;
6256 WERROR result = WERR_OK;
6257 struct dcerpc_binding_handle *b;
6258 TALLOC_CTX *tmp_ctx;
6259 bool ok;
6261 tmp_ctx = talloc_new(mem_ctx);
6262 if (!tmp_ctx) {
6263 return WERR_NOMEM;
6266 result = winreg_printer_binding_handle(tmp_ctx,
6267 session_info,
6268 msg_ctx,
6269 &b);
6270 if (!W_ERROR_IS_OK(result)) {
6271 goto done;
6274 if (printer->drivername != NULL &&
6275 (force_update ||
6276 !strequal(printer->drivername, old_printer->drivername))) {
6277 ok = push_reg_sz(tmp_ctx, &buffer, printer->drivername);
6278 if (!ok) {
6279 DEBUG(0, ("%s data corrupted\n", SPOOL_REG_DRIVERNAME));
6280 result = WERR_INVALID_DATA;
6281 goto done;
6283 result = winreg_set_printer_dataex(tmp_ctx, b,
6284 printer->sharename,
6285 SPOOL_DSSPOOLER_KEY,
6286 SPOOL_REG_DRIVERNAME,
6287 REG_SZ,
6288 buffer.data,
6289 buffer.length);
6290 if (!W_ERROR_IS_OK(result)) {
6291 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DRIVERNAME));
6292 goto done;
6295 if (!force_update) {
6296 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6297 printer->drivername));
6299 notify_printer_driver(server_event_context(), msg_ctx,
6300 snum, printer->drivername ?
6301 printer->drivername : "");
6305 if (printer->comment != NULL &&
6306 (force_update ||
6307 !strequal(printer->comment, old_printer->comment))) {
6308 ok = push_reg_sz(tmp_ctx, &buffer, printer->comment);
6309 if (!ok) {
6310 DEBUG(0, ("comment data corrupted\n"));
6311 result = WERR_INVALID_DATA;
6312 goto done;
6314 result = winreg_set_printer_dataex(tmp_ctx, b,
6315 printer->sharename,
6316 SPOOL_DSSPOOLER_KEY,
6317 SPOOL_REG_DESCRIPTION,
6318 REG_SZ,
6319 buffer.data,
6320 buffer.length);
6321 if (!W_ERROR_IS_OK(result)) {
6322 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DESCRIPTION));
6323 goto done;
6326 if (!force_update) {
6327 notify_printer_comment(server_event_context(), msg_ctx,
6328 snum, printer->comment ?
6329 printer->comment : "");
6333 if (printer->sharename != NULL &&
6334 (force_update ||
6335 !strequal(printer->sharename, old_printer->sharename))) {
6336 ok = push_reg_sz(tmp_ctx, &buffer, printer->sharename);
6337 if (!ok) {
6338 DEBUG(0, ("sharename data corrupted\n"));
6339 result = WERR_INVALID_DATA;
6340 goto done;
6342 result = winreg_set_printer_dataex(tmp_ctx, b,
6343 printer->sharename,
6344 SPOOL_DSSPOOLER_KEY,
6345 SPOOL_REG_PRINTSHARENAME,
6346 REG_SZ,
6347 buffer.data,
6348 buffer.length);
6349 if (!W_ERROR_IS_OK(result)) {
6350 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
6351 goto done;
6354 if (!force_update) {
6355 notify_printer_sharename(server_event_context(),
6356 msg_ctx,
6357 snum, printer->sharename ?
6358 printer->sharename : "");
6362 if (printer->printername != NULL &&
6363 (force_update ||
6364 !strequal(printer->printername, old_printer->printername))) {
6365 const char *p;
6367 p = strrchr(printer->printername, '\\' );
6368 if (p != NULL) {
6369 p++;
6370 } else {
6371 p = printer->printername;
6374 ok = push_reg_sz(tmp_ctx, &buffer, p);
6375 if (!ok) {
6376 DEBUG(0, ("printername data corrupted\n"));
6377 result = WERR_INVALID_DATA;
6378 goto done;
6380 result = winreg_set_printer_dataex(tmp_ctx, b,
6381 printer->sharename,
6382 SPOOL_DSSPOOLER_KEY,
6383 SPOOL_REG_PRINTERNAME,
6384 REG_SZ,
6385 buffer.data,
6386 buffer.length);
6387 if (!W_ERROR_IS_OK(result)) {
6388 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
6389 goto done;
6392 if (!force_update) {
6393 notify_printer_printername(server_event_context(),
6394 msg_ctx, snum, p ? p : "");
6398 if (printer->portname != NULL &&
6399 (force_update ||
6400 !strequal(printer->portname, old_printer->portname))) {
6401 ok = push_reg_sz(tmp_ctx, &buffer, printer->portname);
6402 if (!ok) {
6403 DEBUG(0, ("portname data corrupted\n"));
6404 result = WERR_INVALID_DATA;
6405 goto done;
6407 result = winreg_set_printer_dataex(tmp_ctx, b,
6408 printer->sharename,
6409 SPOOL_DSSPOOLER_KEY,
6410 SPOOL_REG_PORTNAME,
6411 REG_SZ,
6412 buffer.data,
6413 buffer.length);
6414 if (!W_ERROR_IS_OK(result)) {
6415 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PORTNAME));
6416 goto done;
6419 if (!force_update) {
6420 notify_printer_port(server_event_context(),
6421 msg_ctx, snum, printer->portname ?
6422 printer->portname : "");
6426 if (printer->location != NULL &&
6427 (force_update ||
6428 !strequal(printer->location, old_printer->location))) {
6429 ok = push_reg_sz(tmp_ctx, &buffer, printer->location);
6430 if (!ok) {
6431 DEBUG(0, ("location data corrupted\n"));
6432 result = WERR_INVALID_DATA;
6433 goto done;
6435 result = winreg_set_printer_dataex(tmp_ctx, b,
6436 printer->sharename,
6437 SPOOL_DSSPOOLER_KEY,
6438 SPOOL_REG_LOCATION,
6439 REG_SZ,
6440 buffer.data,
6441 buffer.length);
6442 if (!W_ERROR_IS_OK(result)) {
6443 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_LOCATION));
6444 goto done;
6447 if (!force_update) {
6448 notify_printer_location(server_event_context(),
6449 msg_ctx, snum,
6450 printer->location ?
6451 printer->location : "");
6455 if (printer->sepfile != NULL &&
6456 (force_update ||
6457 !strequal(printer->sepfile, old_printer->sepfile))) {
6458 ok = push_reg_sz(tmp_ctx, &buffer, printer->sepfile);
6459 if (!ok) {
6460 DEBUG(0, ("sepfile data corrupted\n"));
6461 result = WERR_INVALID_DATA;
6462 goto done;
6464 result = winreg_set_printer_dataex(tmp_ctx, b,
6465 printer->sharename,
6466 SPOOL_DSSPOOLER_KEY,
6467 SPOOL_REG_PRINTSEPARATORFILE,
6468 REG_SZ,
6469 buffer.data,
6470 buffer.length);
6471 if (!W_ERROR_IS_OK(result)) {
6472 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSEPARATORFILE));
6473 goto done;
6476 if (!force_update) {
6477 notify_printer_sepfile(server_event_context(),
6478 msg_ctx, snum,
6479 printer->sepfile ?
6480 printer->sepfile : "");
6484 if (printer->starttime != 0 &&
6485 (force_update ||
6486 printer->starttime != old_printer->starttime)) {
6487 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6488 SIVAL(buffer.data, 0, printer->starttime);
6489 result = winreg_set_printer_dataex(tmp_ctx, b,
6490 printer->sharename,
6491 SPOOL_DSSPOOLER_KEY,
6492 SPOOL_REG_PRINTSTARTTIME,
6493 REG_DWORD,
6494 buffer.data,
6495 buffer.length);
6496 if (!W_ERROR_IS_OK(result)) {
6497 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSTARTTIME));
6498 goto done;
6502 if (printer->untiltime != 0 &&
6503 (force_update ||
6504 printer->untiltime != old_printer->untiltime)) {
6505 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6506 SIVAL(buffer.data, 0, printer->untiltime);
6507 result = winreg_set_printer_dataex(tmp_ctx, b,
6508 printer->sharename,
6509 SPOOL_DSSPOOLER_KEY,
6510 SPOOL_REG_PRINTENDTIME,
6511 REG_DWORD,
6512 buffer.data,
6513 buffer.length);
6514 if (!W_ERROR_IS_OK(result)) {
6515 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6516 goto done;
6520 if (force_update || printer->priority != old_printer->priority) {
6521 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6522 SIVAL(buffer.data, 0, printer->priority);
6523 result = winreg_set_printer_dataex(tmp_ctx, b,
6524 printer->sharename,
6525 SPOOL_DSSPOOLER_KEY,
6526 SPOOL_REG_PRIORITY,
6527 REG_DWORD,
6528 buffer.data,
6529 buffer.length);
6530 if (!W_ERROR_IS_OK(result)) {
6531 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6532 goto done;
6536 if (force_update || printer->attributes != old_printer->attributes) {
6537 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6538 SIVAL(buffer.data, 0, (printer->attributes &
6539 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6540 result = winreg_set_printer_dataex(tmp_ctx, b,
6541 printer->sharename,
6542 SPOOL_DSSPOOLER_KEY,
6543 SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6544 REG_DWORD,
6545 buffer.data,
6546 buffer.length);
6547 if (!W_ERROR_IS_OK(result)) {
6548 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6549 goto done;
6552 switch (printer->attributes & 0x3) {
6553 case 0:
6554 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6555 break;
6556 case 1:
6557 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6558 break;
6559 case 2:
6560 spooling = SPOOL_REGVAL_PRINTDIRECT;
6561 break;
6562 default:
6563 spooling = "unknown";
6565 ok = push_reg_sz(tmp_ctx, &buffer, spooling);
6566 if (!ok) {
6567 DEBUG(0, ("printSpooling data corrupted\n"));
6568 result = WERR_INVALID_DATA;
6569 goto done;
6571 winreg_set_printer_dataex(tmp_ctx, b,
6572 printer->sharename,
6573 SPOOL_DSSPOOLER_KEY,
6574 SPOOL_REG_PRINTSPOOLING,
6575 REG_SZ,
6576 buffer.data,
6577 buffer.length);
6580 ok = push_reg_sz(tmp_ctx, &buffer, lp_netbios_name());
6581 if (!ok) {
6582 DEBUG(0, ("shortServerName data corrupted\n"));
6583 result = WERR_INVALID_DATA;
6584 goto done;
6586 result = winreg_set_printer_dataex(tmp_ctx, b,
6587 printer->sharename,
6588 SPOOL_DSSPOOLER_KEY,
6589 SPOOL_REG_SHORTSERVERNAME,
6590 REG_SZ,
6591 buffer.data,
6592 buffer.length);
6593 if (!W_ERROR_IS_OK(result)) {
6594 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SHORTSERVERNAME));
6595 goto done;
6598 dnsdomname = get_mydnsfullname();
6599 if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6600 longname = talloc_strdup(tmp_ctx, dnsdomname);
6601 } else {
6602 longname = talloc_strdup(tmp_ctx, lp_netbios_name());
6604 if (longname == NULL) {
6605 result = WERR_NOMEM;
6606 goto done;
6609 ok = push_reg_sz(tmp_ctx, &buffer, longname);
6610 if (!ok) {
6611 DEBUG(0, ("longname data corrupted\n"));
6612 result = WERR_INVALID_DATA;
6613 goto done;
6615 result = winreg_set_printer_dataex(tmp_ctx, b,
6616 printer->sharename,
6617 SPOOL_DSSPOOLER_KEY,
6618 SPOOL_REG_SERVERNAME,
6619 REG_SZ,
6620 buffer.data,
6621 buffer.length);
6622 if (!W_ERROR_IS_OK(result)) {
6623 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SERVERNAME));
6624 goto done;
6627 uncname = talloc_asprintf(tmp_ctx, "\\\\%s\\%s",
6628 lp_netbios_name(), printer->sharename);
6629 ok = push_reg_sz(tmp_ctx, &buffer, uncname);
6630 if (!ok) {
6631 DEBUG(0, ("uncName data corrupted\n"));
6632 result = WERR_INVALID_DATA;
6633 goto done;
6635 result = winreg_set_printer_dataex(tmp_ctx, b,
6636 printer->sharename,
6637 SPOOL_DSSPOOLER_KEY,
6638 SPOOL_REG_UNCNAME,
6639 REG_SZ,
6640 buffer.data,
6641 buffer.length);
6642 if (!W_ERROR_IS_OK(result)) {
6643 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_UNCNAME));
6644 goto done;
6647 done:
6648 talloc_free(tmp_ctx);
6649 return result;
6652 /********************************************************************
6653 * Called by spoolss_api_setprinter
6654 * when updating a printer description.
6655 ********************************************************************/
6657 static WERROR update_printer(struct pipes_struct *p,
6658 struct policy_handle *handle,
6659 struct spoolss_SetPrinterInfoCtr *info_ctr,
6660 struct spoolss_DeviceMode *devmode)
6662 uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6663 struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6664 struct spoolss_PrinterInfo2 *old_printer;
6665 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6666 int snum;
6667 WERROR result = WERR_OK;
6668 TALLOC_CTX *tmp_ctx;
6669 struct dcerpc_binding_handle *b;
6671 DEBUG(8,("update_printer\n"));
6673 tmp_ctx = talloc_new(p->mem_ctx);
6674 if (tmp_ctx == NULL) {
6675 return WERR_NOMEM;
6678 if (!Printer) {
6679 result = WERR_BADFID;
6680 goto done;
6683 if (!get_printer_snum(p, handle, &snum, NULL)) {
6684 result = WERR_BADFID;
6685 goto done;
6688 result = winreg_printer_binding_handle(tmp_ctx,
6689 get_session_info_system(),
6690 p->msg_ctx,
6691 &b);
6692 if (!W_ERROR_IS_OK(result)) {
6693 goto done;
6696 result = winreg_get_printer(tmp_ctx, b,
6697 lp_const_servicename(snum),
6698 &old_printer);
6699 if (!W_ERROR_IS_OK(result)) {
6700 result = WERR_BADFID;
6701 goto done;
6704 /* Do sanity check on the requested changes for Samba */
6705 if (!check_printer_ok(tmp_ctx, printer, snum)) {
6706 result = WERR_INVALID_PARAM;
6707 goto done;
6710 /* FIXME!!! If the driver has changed we really should verify that
6711 it is installed before doing much else --jerry */
6713 /* Check calling user has permission to update printer description */
6714 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6715 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6716 result = WERR_ACCESS_DENIED;
6717 goto done;
6720 /* Call addprinter hook */
6721 /* Check changes to see if this is really needed */
6723 if (*lp_addprinter_cmd() &&
6724 (!strequal(printer->drivername, old_printer->drivername) ||
6725 !strequal(printer->comment, old_printer->comment) ||
6726 !strequal(printer->portname, old_printer->portname) ||
6727 !strequal(printer->location, old_printer->location)) )
6729 char *raddr;
6731 raddr = tsocket_address_inet_addr_string(p->remote_address,
6732 p->mem_ctx);
6733 if (raddr == NULL) {
6734 return WERR_NOMEM;
6737 /* add_printer_hook() will call reload_services() */
6738 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6739 printer, raddr,
6740 p->msg_ctx)) {
6741 result = WERR_ACCESS_DENIED;
6742 goto done;
6746 result = update_dsspooler(tmp_ctx,
6747 get_session_info_system(),
6748 p->msg_ctx,
6749 snum,
6750 printer,
6751 old_printer);
6752 if (!W_ERROR_IS_OK(result)) {
6753 goto done;
6756 printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6758 if (devmode == NULL) {
6759 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6761 result = winreg_update_printer(tmp_ctx, b,
6762 printer->sharename,
6763 printer_mask,
6764 printer,
6765 devmode,
6766 NULL);
6768 done:
6769 talloc_free(tmp_ctx);
6771 return result;
6774 /****************************************************************************
6775 ****************************************************************************/
6776 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6777 struct policy_handle *handle,
6778 struct spoolss_SetPrinterInfo7 *info7)
6780 #ifdef HAVE_ADS
6781 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6782 WERROR result;
6783 int snum;
6784 struct printer_handle *Printer;
6786 if ( lp_security() != SEC_ADS ) {
6787 return WERR_UNKNOWN_LEVEL;
6790 Printer = find_printer_index_by_hnd(p, handle);
6792 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6794 if (!Printer)
6795 return WERR_BADFID;
6797 if (!get_printer_snum(p, handle, &snum, NULL))
6798 return WERR_BADFID;
6800 result = winreg_get_printer_internal(p->mem_ctx,
6801 get_session_info_system(),
6802 p->msg_ctx,
6803 lp_servicename(snum),
6804 &pinfo2);
6805 if (!W_ERROR_IS_OK(result)) {
6806 return WERR_BADFID;
6809 nt_printer_publish(pinfo2,
6810 get_session_info_system(),
6811 p->msg_ctx,
6812 pinfo2,
6813 info7->action);
6815 TALLOC_FREE(pinfo2);
6816 return WERR_OK;
6817 #else
6818 return WERR_UNKNOWN_LEVEL;
6819 #endif
6822 /********************************************************************
6823 ********************************************************************/
6825 static WERROR update_printer_devmode(struct pipes_struct *p,
6826 struct policy_handle *handle,
6827 struct spoolss_DeviceMode *devmode)
6829 int snum;
6830 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6831 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6833 DEBUG(8,("update_printer_devmode\n"));
6835 if (!Printer) {
6836 return WERR_BADFID;
6839 if (!get_printer_snum(p, handle, &snum, NULL)) {
6840 return WERR_BADFID;
6843 /* Check calling user has permission to update printer description */
6844 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6845 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6846 return WERR_ACCESS_DENIED;
6849 return winreg_update_printer_internal(p->mem_ctx,
6850 get_session_info_system(),
6851 p->msg_ctx,
6852 lp_const_servicename(snum),
6853 info2_mask,
6854 NULL,
6855 devmode,
6856 NULL);
6860 /****************************************************************
6861 _spoolss_SetPrinter
6862 ****************************************************************/
6864 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6865 struct spoolss_SetPrinter *r)
6867 WERROR result;
6869 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6871 if (!Printer) {
6872 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6873 OUR_HANDLE(r->in.handle)));
6874 return WERR_BADFID;
6877 /* check the level */
6878 switch (r->in.info_ctr->level) {
6879 case 0:
6880 return control_printer(r->in.handle, r->in.command, p);
6881 case 2:
6882 result = update_printer(p, r->in.handle,
6883 r->in.info_ctr,
6884 r->in.devmode_ctr->devmode);
6885 if (!W_ERROR_IS_OK(result))
6886 return result;
6887 if (r->in.secdesc_ctr->sd)
6888 result = update_printer_sec(r->in.handle, p,
6889 r->in.secdesc_ctr);
6890 return result;
6891 case 3:
6892 return update_printer_sec(r->in.handle, p,
6893 r->in.secdesc_ctr);
6894 case 7:
6895 return publish_or_unpublish_printer(p, r->in.handle,
6896 r->in.info_ctr->info.info7);
6897 case 8:
6898 return update_printer_devmode(p, r->in.handle,
6899 r->in.devmode_ctr->devmode);
6900 default:
6901 return WERR_UNKNOWN_LEVEL;
6905 /****************************************************************
6906 _spoolss_FindClosePrinterNotify
6907 ****************************************************************/
6909 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
6910 struct spoolss_FindClosePrinterNotify *r)
6912 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6914 if (!Printer) {
6915 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6916 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6917 return WERR_BADFID;
6920 if (Printer->notify.cli_chan != NULL &&
6921 Printer->notify.cli_chan->active_connections > 0) {
6922 int snum = -1;
6924 if (Printer->printer_type == SPLHND_PRINTER) {
6925 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6926 return WERR_BADFID;
6930 srv_spoolss_replycloseprinter(snum, Printer);
6933 Printer->notify.flags=0;
6934 Printer->notify.options=0;
6935 Printer->notify.localmachine[0]='\0';
6936 Printer->notify.printerlocal=0;
6937 TALLOC_FREE(Printer->notify.option);
6939 return WERR_OK;
6942 /****************************************************************
6943 _spoolss_AddJob
6944 ****************************************************************/
6946 WERROR _spoolss_AddJob(struct pipes_struct *p,
6947 struct spoolss_AddJob *r)
6949 if (!r->in.buffer && (r->in.offered != 0)) {
6950 return WERR_INVALID_PARAM;
6953 /* this is what a NT server returns for AddJob. AddJob must fail on
6954 * non-local printers */
6956 if (r->in.level != 1) {
6957 return WERR_UNKNOWN_LEVEL;
6960 return WERR_INVALID_PARAM;
6963 /****************************************************************************
6964 fill_job_info1
6965 ****************************************************************************/
6967 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6968 struct spoolss_JobInfo1 *r,
6969 const print_queue_struct *queue,
6970 int position, int snum,
6971 struct spoolss_PrinterInfo2 *pinfo2)
6973 struct tm *t;
6975 t = gmtime(&queue->time);
6977 r->job_id = queue->job;
6979 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6980 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6981 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
6982 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6983 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6984 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6985 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6986 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6987 r->data_type = talloc_strdup(mem_ctx, "RAW");
6988 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6989 r->text_status = talloc_strdup(mem_ctx, "");
6990 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6992 r->status = nt_printj_status(queue->status);
6993 r->priority = queue->priority;
6994 r->position = position;
6995 r->total_pages = queue->page_count;
6996 r->pages_printed = 0; /* ??? */
6998 init_systemtime(&r->submitted, t);
7000 return WERR_OK;
7003 /****************************************************************************
7004 fill_job_info2
7005 ****************************************************************************/
7007 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
7008 struct spoolss_JobInfo2 *r,
7009 const print_queue_struct *queue,
7010 int position, int snum,
7011 struct spoolss_PrinterInfo2 *pinfo2,
7012 struct spoolss_DeviceMode *devmode)
7014 struct tm *t;
7016 t = gmtime(&queue->time);
7018 r->job_id = queue->job;
7020 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
7021 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
7022 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
7023 W_ERROR_HAVE_NO_MEMORY(r->server_name);
7024 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
7025 W_ERROR_HAVE_NO_MEMORY(r->user_name);
7026 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
7027 W_ERROR_HAVE_NO_MEMORY(r->document_name);
7028 r->notify_name = talloc_strdup(mem_ctx, queue->fs_user);
7029 W_ERROR_HAVE_NO_MEMORY(r->notify_name);
7030 r->data_type = talloc_strdup(mem_ctx, "RAW");
7031 W_ERROR_HAVE_NO_MEMORY(r->data_type);
7032 r->print_processor = talloc_strdup(mem_ctx, "winprint");
7033 W_ERROR_HAVE_NO_MEMORY(r->print_processor);
7034 r->parameters = talloc_strdup(mem_ctx, "");
7035 W_ERROR_HAVE_NO_MEMORY(r->parameters);
7036 r->driver_name = talloc_strdup(mem_ctx, pinfo2->drivername);
7037 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
7039 r->devmode = devmode;
7041 r->text_status = talloc_strdup(mem_ctx, "");
7042 W_ERROR_HAVE_NO_MEMORY(r->text_status);
7044 r->secdesc = NULL;
7046 r->status = nt_printj_status(queue->status);
7047 r->priority = queue->priority;
7048 r->position = position;
7049 r->start_time = 0;
7050 r->until_time = 0;
7051 r->total_pages = queue->page_count;
7052 r->size = queue->size;
7053 init_systemtime(&r->submitted, t);
7054 r->time = 0;
7055 r->pages_printed = 0; /* ??? */
7057 return WERR_OK;
7060 /****************************************************************************
7061 fill_job_info3
7062 ****************************************************************************/
7064 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
7065 struct spoolss_JobInfo3 *r,
7066 const print_queue_struct *queue,
7067 const print_queue_struct *next_queue,
7068 int position, int snum,
7069 struct spoolss_PrinterInfo2 *pinfo2)
7071 r->job_id = queue->job;
7072 r->next_job_id = 0;
7073 if (next_queue) {
7074 r->next_job_id = next_queue->job;
7076 r->reserved = 0;
7078 return WERR_OK;
7081 /****************************************************************************
7082 Enumjobs at level 1.
7083 ****************************************************************************/
7085 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
7086 const print_queue_struct *queue,
7087 uint32_t num_queues, int snum,
7088 struct spoolss_PrinterInfo2 *pinfo2,
7089 union spoolss_JobInfo **info_p,
7090 uint32_t *count)
7092 union spoolss_JobInfo *info;
7093 int i;
7094 WERROR result = WERR_OK;
7096 info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7097 W_ERROR_HAVE_NO_MEMORY(info);
7099 *count = num_queues;
7101 for (i=0; i<*count; i++) {
7102 result = fill_job_info1(info,
7103 &info[i].info1,
7104 &queue[i],
7106 snum,
7107 pinfo2);
7108 if (!W_ERROR_IS_OK(result)) {
7109 goto out;
7113 out:
7114 if (!W_ERROR_IS_OK(result)) {
7115 TALLOC_FREE(info);
7116 *count = 0;
7117 return result;
7120 *info_p = info;
7122 return WERR_OK;
7125 /****************************************************************************
7126 Enumjobs at level 2.
7127 ****************************************************************************/
7129 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
7130 const print_queue_struct *queue,
7131 uint32_t num_queues, int snum,
7132 struct spoolss_PrinterInfo2 *pinfo2,
7133 union spoolss_JobInfo **info_p,
7134 uint32_t *count)
7136 union spoolss_JobInfo *info;
7137 int i;
7138 WERROR result = WERR_OK;
7140 info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7141 W_ERROR_HAVE_NO_MEMORY(info);
7143 *count = num_queues;
7145 for (i=0; i<*count; i++) {
7146 struct spoolss_DeviceMode *devmode;
7148 result = spoolss_create_default_devmode(info,
7149 pinfo2->printername,
7150 &devmode);
7151 if (!W_ERROR_IS_OK(result)) {
7152 DEBUG(3, ("Can't proceed w/o a devmode!"));
7153 goto out;
7156 result = fill_job_info2(info,
7157 &info[i].info2,
7158 &queue[i],
7160 snum,
7161 pinfo2,
7162 devmode);
7163 if (!W_ERROR_IS_OK(result)) {
7164 goto out;
7168 out:
7169 if (!W_ERROR_IS_OK(result)) {
7170 TALLOC_FREE(info);
7171 *count = 0;
7172 return result;
7175 *info_p = info;
7177 return WERR_OK;
7180 /****************************************************************************
7181 Enumjobs at level 3.
7182 ****************************************************************************/
7184 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
7185 const print_queue_struct *queue,
7186 uint32_t num_queues, int snum,
7187 struct spoolss_PrinterInfo2 *pinfo2,
7188 union spoolss_JobInfo **info_p,
7189 uint32_t *count)
7191 union spoolss_JobInfo *info;
7192 int i;
7193 WERROR result = WERR_OK;
7195 info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7196 W_ERROR_HAVE_NO_MEMORY(info);
7198 *count = num_queues;
7200 for (i=0; i<*count; i++) {
7201 const print_queue_struct *next_queue = NULL;
7203 if (i+1 < *count) {
7204 next_queue = &queue[i+1];
7207 result = fill_job_info3(info,
7208 &info[i].info3,
7209 &queue[i],
7210 next_queue,
7212 snum,
7213 pinfo2);
7214 if (!W_ERROR_IS_OK(result)) {
7215 goto out;
7219 out:
7220 if (!W_ERROR_IS_OK(result)) {
7221 TALLOC_FREE(info);
7222 *count = 0;
7223 return result;
7226 *info_p = info;
7228 return WERR_OK;
7231 /****************************************************************
7232 _spoolss_EnumJobs
7233 ****************************************************************/
7235 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7236 struct spoolss_EnumJobs *r)
7238 WERROR result;
7239 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7240 int snum;
7241 print_status_struct prt_status;
7242 print_queue_struct *queue = NULL;
7243 uint32_t count;
7245 /* that's an [in out] buffer */
7247 if (!r->in.buffer && (r->in.offered != 0)) {
7248 return WERR_INVALID_PARAM;
7251 DEBUG(4,("_spoolss_EnumJobs\n"));
7253 *r->out.needed = 0;
7254 *r->out.count = 0;
7255 *r->out.info = NULL;
7257 /* lookup the printer snum and tdb entry */
7259 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7260 return WERR_BADFID;
7263 result = winreg_get_printer_internal(p->mem_ctx,
7264 get_session_info_system(),
7265 p->msg_ctx,
7266 lp_const_servicename(snum),
7267 &pinfo2);
7268 if (!W_ERROR_IS_OK(result)) {
7269 return result;
7272 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7273 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7274 count, prt_status.status, prt_status.message));
7276 if (count == 0) {
7277 SAFE_FREE(queue);
7278 TALLOC_FREE(pinfo2);
7279 return WERR_OK;
7282 switch (r->in.level) {
7283 case 1:
7284 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7285 pinfo2, r->out.info, r->out.count);
7286 break;
7287 case 2:
7288 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7289 pinfo2, r->out.info, r->out.count);
7290 break;
7291 case 3:
7292 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7293 pinfo2, r->out.info, r->out.count);
7294 break;
7295 default:
7296 result = WERR_UNKNOWN_LEVEL;
7297 break;
7300 SAFE_FREE(queue);
7301 TALLOC_FREE(pinfo2);
7303 if (!W_ERROR_IS_OK(result)) {
7304 return result;
7307 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7308 spoolss_EnumJobs,
7309 *r->out.info, r->in.level,
7310 *r->out.count);
7311 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7312 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7314 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7317 /****************************************************************
7318 _spoolss_ScheduleJob
7319 ****************************************************************/
7321 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7322 struct spoolss_ScheduleJob *r)
7324 return WERR_OK;
7327 /****************************************************************
7328 ****************************************************************/
7330 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7331 struct messaging_context *msg_ctx,
7332 const char *printer_name,
7333 uint32_t job_id,
7334 struct spoolss_SetJobInfo1 *r)
7336 char *old_doc_name;
7338 if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7339 return WERR_BADFID;
7342 if (strequal(old_doc_name, r->document_name)) {
7343 return WERR_OK;
7346 if (!print_job_set_name(server_event_context(), msg_ctx,
7347 printer_name, job_id, r->document_name)) {
7348 return WERR_BADFID;
7351 return WERR_OK;
7354 /****************************************************************
7355 _spoolss_SetJob
7356 ****************************************************************/
7358 WERROR _spoolss_SetJob(struct pipes_struct *p,
7359 struct spoolss_SetJob *r)
7361 const struct auth_session_info *session_info = p->session_info;
7362 int snum;
7363 WERROR errcode = WERR_BADFUNC;
7365 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7366 return WERR_BADFID;
7369 if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7370 return WERR_INVALID_PRINTER_NAME;
7373 switch (r->in.command) {
7374 case SPOOLSS_JOB_CONTROL_CANCEL:
7375 case SPOOLSS_JOB_CONTROL_DELETE:
7376 errcode = print_job_delete(session_info, p->msg_ctx,
7377 snum, r->in.job_id);
7378 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7379 errcode = WERR_OK;
7381 break;
7382 case SPOOLSS_JOB_CONTROL_PAUSE:
7383 if (print_job_pause(session_info, p->msg_ctx,
7384 snum, r->in.job_id, &errcode)) {
7385 errcode = WERR_OK;
7387 break;
7388 case SPOOLSS_JOB_CONTROL_RESTART:
7389 case SPOOLSS_JOB_CONTROL_RESUME:
7390 if (print_job_resume(session_info, p->msg_ctx,
7391 snum, r->in.job_id, &errcode)) {
7392 errcode = WERR_OK;
7394 break;
7395 case 0:
7396 errcode = WERR_OK;
7397 break;
7398 default:
7399 return WERR_UNKNOWN_LEVEL;
7402 if (!W_ERROR_IS_OK(errcode)) {
7403 return errcode;
7406 if (r->in.ctr == NULL) {
7407 return errcode;
7410 switch (r->in.ctr->level) {
7411 case 1:
7412 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7413 lp_const_servicename(snum),
7414 r->in.job_id,
7415 r->in.ctr->info.info1);
7416 break;
7417 case 2:
7418 case 3:
7419 case 4:
7420 default:
7421 return WERR_UNKNOWN_LEVEL;
7424 return errcode;
7427 /****************************************************************************
7428 Enumerates all printer drivers by level and architecture.
7429 ****************************************************************************/
7431 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7432 const struct auth_session_info *session_info,
7433 struct messaging_context *msg_ctx,
7434 const char *servername,
7435 const char *architecture,
7436 uint32_t level,
7437 union spoolss_DriverInfo **info_p,
7438 uint32_t *count_p)
7440 int i;
7441 uint32_t version;
7442 struct spoolss_DriverInfo8 *driver;
7443 union spoolss_DriverInfo *info = NULL;
7444 uint32_t count = 0;
7445 WERROR result = WERR_OK;
7446 uint32_t num_drivers;
7447 const char **drivers;
7448 struct dcerpc_binding_handle *b;
7449 TALLOC_CTX *tmp_ctx = NULL;
7451 *count_p = 0;
7452 *info_p = NULL;
7454 tmp_ctx = talloc_new(mem_ctx);
7455 if (!tmp_ctx) {
7456 return WERR_NOMEM;
7459 result = winreg_printer_binding_handle(tmp_ctx,
7460 session_info,
7461 msg_ctx,
7462 &b);
7463 if (!W_ERROR_IS_OK(result)) {
7464 goto out;
7467 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7468 result = winreg_get_driver_list(tmp_ctx, b,
7469 architecture, version,
7470 &num_drivers, &drivers);
7471 if (!W_ERROR_IS_OK(result)) {
7472 goto out;
7474 DEBUG(4, ("we have:[%d] drivers in environment"
7475 " [%s] and version [%d]\n",
7476 num_drivers, architecture, version));
7478 if (num_drivers != 0) {
7479 info = talloc_realloc(tmp_ctx, info,
7480 union spoolss_DriverInfo,
7481 count + num_drivers);
7482 if (!info) {
7483 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7484 "failed to enlarge driver info buffer!\n"));
7485 result = WERR_NOMEM;
7486 goto out;
7490 for (i = 0; i < num_drivers; i++) {
7491 DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7493 result = winreg_get_driver(tmp_ctx, b,
7494 architecture, drivers[i],
7495 version, &driver);
7496 if (!W_ERROR_IS_OK(result)) {
7497 goto out;
7500 switch (level) {
7501 case 1:
7502 result = fill_printer_driver_info1(info, &info[count+i].info1,
7503 driver, servername);
7504 break;
7505 case 2:
7506 result = fill_printer_driver_info2(info, &info[count+i].info2,
7507 driver, servername);
7508 break;
7509 case 3:
7510 result = fill_printer_driver_info3(info, &info[count+i].info3,
7511 driver, servername);
7512 break;
7513 case 4:
7514 result = fill_printer_driver_info4(info, &info[count+i].info4,
7515 driver, servername);
7516 break;
7517 case 5:
7518 result = fill_printer_driver_info5(info, &info[count+i].info5,
7519 driver, servername);
7520 break;
7521 case 6:
7522 result = fill_printer_driver_info6(info, &info[count+i].info6,
7523 driver, servername);
7524 break;
7525 case 8:
7526 result = fill_printer_driver_info8(info, &info[count+i].info8,
7527 driver, servername);
7528 break;
7529 default:
7530 result = WERR_UNKNOWN_LEVEL;
7531 break;
7534 TALLOC_FREE(driver);
7536 if (!W_ERROR_IS_OK(result)) {
7537 goto out;
7541 count += num_drivers;
7542 TALLOC_FREE(drivers);
7545 out:
7546 if (W_ERROR_IS_OK(result)) {
7547 *info_p = talloc_move(mem_ctx, &info);
7548 *count_p = count;
7551 talloc_free(tmp_ctx);
7552 return result;
7555 /****************************************************************************
7556 Enumerates all printer drivers by level.
7557 ****************************************************************************/
7559 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7560 const struct auth_session_info *session_info,
7561 struct messaging_context *msg_ctx,
7562 const char *servername,
7563 const char *architecture,
7564 uint32_t level,
7565 union spoolss_DriverInfo **info_p,
7566 uint32_t *count_p)
7568 uint32_t a,i;
7569 WERROR result = WERR_OK;
7571 if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7573 for (a=0; archi_table[a].long_archi != NULL; a++) {
7575 union spoolss_DriverInfo *info = NULL;
7576 uint32_t count = 0;
7578 result = enumprinterdrivers_level_by_architecture(mem_ctx,
7579 session_info,
7580 msg_ctx,
7581 servername,
7582 archi_table[a].long_archi,
7583 level,
7584 &info,
7585 &count);
7586 if (!W_ERROR_IS_OK(result)) {
7587 continue;
7590 for (i=0; i < count; i++) {
7591 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7592 info[i], info_p, count_p);
7596 return result;
7599 return enumprinterdrivers_level_by_architecture(mem_ctx,
7600 session_info,
7601 msg_ctx,
7602 servername,
7603 architecture,
7604 level,
7605 info_p,
7606 count_p);
7609 /****************************************************************
7610 _spoolss_EnumPrinterDrivers
7611 ****************************************************************/
7613 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7614 struct spoolss_EnumPrinterDrivers *r)
7616 const char *cservername;
7617 WERROR result;
7619 /* that's an [in out] buffer */
7621 if (!r->in.buffer && (r->in.offered != 0)) {
7622 return WERR_INVALID_PARAM;
7625 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7627 *r->out.needed = 0;
7628 *r->out.count = 0;
7629 *r->out.info = NULL;
7631 cservername = canon_servername(r->in.server);
7633 if (!is_myname_or_ipaddr(cservername)) {
7634 return WERR_UNKNOWN_PRINTER_DRIVER;
7637 result = enumprinterdrivers_level(p->mem_ctx,
7638 get_session_info_system(),
7639 p->msg_ctx,
7640 cservername,
7641 r->in.environment,
7642 r->in.level,
7643 r->out.info,
7644 r->out.count);
7645 if (!W_ERROR_IS_OK(result)) {
7646 return result;
7649 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7650 spoolss_EnumPrinterDrivers,
7651 *r->out.info, r->in.level,
7652 *r->out.count);
7653 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7654 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7656 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7659 /****************************************************************
7660 _spoolss_EnumForms
7661 ****************************************************************/
7663 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7664 struct spoolss_EnumForms *r)
7666 WERROR result;
7668 *r->out.count = 0;
7669 *r->out.needed = 0;
7670 *r->out.info = NULL;
7672 /* that's an [in out] buffer */
7674 if (!r->in.buffer && (r->in.offered != 0) ) {
7675 return WERR_INVALID_PARAM;
7678 DEBUG(4,("_spoolss_EnumForms\n"));
7679 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7680 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7682 switch (r->in.level) {
7683 case 1:
7684 result = winreg_printer_enumforms1_internal(p->mem_ctx,
7685 get_session_info_system(),
7686 p->msg_ctx,
7687 r->out.count,
7688 r->out.info);
7689 break;
7690 default:
7691 result = WERR_UNKNOWN_LEVEL;
7692 break;
7695 if (!W_ERROR_IS_OK(result)) {
7696 return result;
7699 if (*r->out.count == 0) {
7700 return WERR_NO_MORE_ITEMS;
7703 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7704 spoolss_EnumForms,
7705 *r->out.info, r->in.level,
7706 *r->out.count);
7707 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7708 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7710 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7713 /****************************************************************
7714 _spoolss_GetForm
7715 ****************************************************************/
7717 WERROR _spoolss_GetForm(struct pipes_struct *p,
7718 struct spoolss_GetForm *r)
7720 WERROR result;
7722 /* that's an [in out] buffer */
7724 if (!r->in.buffer && (r->in.offered != 0)) {
7725 return WERR_INVALID_PARAM;
7728 DEBUG(4,("_spoolss_GetForm\n"));
7729 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7730 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7732 switch (r->in.level) {
7733 case 1:
7734 result = winreg_printer_getform1_internal(p->mem_ctx,
7735 get_session_info_system(),
7736 p->msg_ctx,
7737 r->in.form_name,
7738 &r->out.info->info1);
7739 break;
7740 default:
7741 result = WERR_UNKNOWN_LEVEL;
7742 break;
7745 if (!W_ERROR_IS_OK(result)) {
7746 TALLOC_FREE(r->out.info);
7747 return result;
7750 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
7751 r->out.info, r->in.level);
7752 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7754 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7757 /****************************************************************************
7758 ****************************************************************************/
7760 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7761 struct spoolss_PortInfo1 *r,
7762 const char *name)
7764 r->port_name = talloc_strdup(mem_ctx, name);
7765 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7767 return WERR_OK;
7770 /****************************************************************************
7771 TODO: This probably needs distinguish between TCP/IP and Local ports
7772 somehow.
7773 ****************************************************************************/
7775 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7776 struct spoolss_PortInfo2 *r,
7777 const char *name)
7779 r->port_name = talloc_strdup(mem_ctx, name);
7780 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7782 r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7783 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7785 r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7786 W_ERROR_HAVE_NO_MEMORY(r->description);
7788 r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7789 r->reserved = 0;
7791 return WERR_OK;
7795 /****************************************************************************
7796 wrapper around the enumer ports command
7797 ****************************************************************************/
7799 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7801 char *cmd = lp_enumports_cmd();
7802 char **qlines = NULL;
7803 char *command = NULL;
7804 int numlines;
7805 int ret;
7806 int fd;
7808 *count = 0;
7809 *lines = NULL;
7811 /* if no hook then just fill in the default port */
7813 if ( !*cmd ) {
7814 if (!(qlines = talloc_array( NULL, char*, 2 ))) {
7815 return WERR_NOMEM;
7817 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7818 TALLOC_FREE(qlines);
7819 return WERR_NOMEM;
7821 qlines[1] = NULL;
7822 numlines = 1;
7824 else {
7825 /* we have a valid enumport command */
7827 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7828 if (!command) {
7829 return WERR_NOMEM;
7832 DEBUG(10,("Running [%s]\n", command));
7833 ret = smbrun(command, &fd);
7834 DEBUG(10,("Returned [%d]\n", ret));
7835 TALLOC_FREE(command);
7836 if (ret != 0) {
7837 if (fd != -1) {
7838 close(fd);
7840 return WERR_ACCESS_DENIED;
7843 numlines = 0;
7844 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7845 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7846 close(fd);
7849 *count = numlines;
7850 *lines = qlines;
7852 return WERR_OK;
7855 /****************************************************************************
7856 enumports level 1.
7857 ****************************************************************************/
7859 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7860 union spoolss_PortInfo **info_p,
7861 uint32_t *count)
7863 union spoolss_PortInfo *info = NULL;
7864 int i=0;
7865 WERROR result = WERR_OK;
7866 char **qlines = NULL;
7867 int numlines = 0;
7869 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7870 if (!W_ERROR_IS_OK(result)) {
7871 goto out;
7874 if (numlines) {
7875 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
7876 if (!info) {
7877 DEBUG(10,("Returning WERR_NOMEM\n"));
7878 result = WERR_NOMEM;
7879 goto out;
7882 for (i=0; i<numlines; i++) {
7883 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7884 result = fill_port_1(info, &info[i].info1, qlines[i]);
7885 if (!W_ERROR_IS_OK(result)) {
7886 goto out;
7890 TALLOC_FREE(qlines);
7892 out:
7893 if (!W_ERROR_IS_OK(result)) {
7894 TALLOC_FREE(info);
7895 TALLOC_FREE(qlines);
7896 *count = 0;
7897 *info_p = NULL;
7898 return result;
7901 *info_p = info;
7902 *count = numlines;
7904 return WERR_OK;
7907 /****************************************************************************
7908 enumports level 2.
7909 ****************************************************************************/
7911 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7912 union spoolss_PortInfo **info_p,
7913 uint32_t *count)
7915 union spoolss_PortInfo *info = NULL;
7916 int i=0;
7917 WERROR result = WERR_OK;
7918 char **qlines = NULL;
7919 int numlines = 0;
7921 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7922 if (!W_ERROR_IS_OK(result)) {
7923 goto out;
7926 if (numlines) {
7927 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
7928 if (!info) {
7929 DEBUG(10,("Returning WERR_NOMEM\n"));
7930 result = WERR_NOMEM;
7931 goto out;
7934 for (i=0; i<numlines; i++) {
7935 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7936 result = fill_port_2(info, &info[i].info2, qlines[i]);
7937 if (!W_ERROR_IS_OK(result)) {
7938 goto out;
7942 TALLOC_FREE(qlines);
7944 out:
7945 if (!W_ERROR_IS_OK(result)) {
7946 TALLOC_FREE(info);
7947 TALLOC_FREE(qlines);
7948 *count = 0;
7949 *info_p = NULL;
7950 return result;
7953 *info_p = info;
7954 *count = numlines;
7956 return WERR_OK;
7959 /****************************************************************
7960 _spoolss_EnumPorts
7961 ****************************************************************/
7963 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
7964 struct spoolss_EnumPorts *r)
7966 WERROR result;
7968 /* that's an [in out] buffer */
7970 if (!r->in.buffer && (r->in.offered != 0)) {
7971 return WERR_INVALID_PARAM;
7974 DEBUG(4,("_spoolss_EnumPorts\n"));
7976 *r->out.count = 0;
7977 *r->out.needed = 0;
7978 *r->out.info = NULL;
7980 switch (r->in.level) {
7981 case 1:
7982 result = enumports_level_1(p->mem_ctx, r->out.info,
7983 r->out.count);
7984 break;
7985 case 2:
7986 result = enumports_level_2(p->mem_ctx, r->out.info,
7987 r->out.count);
7988 break;
7989 default:
7990 return WERR_UNKNOWN_LEVEL;
7993 if (!W_ERROR_IS_OK(result)) {
7994 return result;
7997 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7998 spoolss_EnumPorts,
7999 *r->out.info, r->in.level,
8000 *r->out.count);
8001 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8002 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8004 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8007 /****************************************************************************
8008 ****************************************************************************/
8010 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
8011 const char *server,
8012 struct spoolss_SetPrinterInfoCtr *info_ctr,
8013 struct spoolss_DeviceMode *devmode,
8014 struct security_descriptor *secdesc,
8015 struct spoolss_UserLevelCtr *user_ctr,
8016 struct policy_handle *handle)
8018 struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
8019 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
8020 int snum;
8021 WERROR err = WERR_OK;
8023 /* samba does not have a concept of local, non-shared printers yet, so
8024 * make sure we always setup sharename - gd */
8025 if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
8026 (info2->printername != NULL && info2->printername[0] != '\0')) {
8027 DEBUG(5, ("spoolss_addprinterex_level_2: "
8028 "no sharename has been set, setting printername %s as sharename\n",
8029 info2->printername));
8030 info2->sharename = info2->printername;
8033 /* check to see if the printer already exists */
8034 if ((snum = print_queue_snum(info2->sharename)) != -1) {
8035 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8036 info2->sharename));
8037 return WERR_PRINTER_ALREADY_EXISTS;
8040 if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
8041 if ((snum = print_queue_snum(info2->printername)) != -1) {
8042 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8043 info2->printername));
8044 return WERR_PRINTER_ALREADY_EXISTS;
8048 /* validate printer info struct */
8049 if (!info2->printername || strlen(info2->printername) == 0) {
8050 return WERR_INVALID_PRINTER_NAME;
8052 if (!info2->portname || strlen(info2->portname) == 0) {
8053 return WERR_UNKNOWN_PORT;
8055 if (!info2->drivername || strlen(info2->drivername) == 0) {
8056 return WERR_UNKNOWN_PRINTER_DRIVER;
8058 if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
8059 return WERR_UNKNOWN_PRINTPROCESSOR;
8062 /* FIXME!!! smbd should check to see if the driver is installed before
8063 trying to add a printer like this --jerry */
8065 if (*lp_addprinter_cmd() ) {
8066 char *raddr;
8068 raddr = tsocket_address_inet_addr_string(p->remote_address,
8069 p->mem_ctx);
8070 if (raddr == NULL) {
8071 return WERR_NOMEM;
8074 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
8075 info2, raddr,
8076 p->msg_ctx) ) {
8077 return WERR_ACCESS_DENIED;
8079 } else {
8080 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
8081 "smb.conf parameter \"addprinter command\" is defined. This "
8082 "parameter must exist for this call to succeed\n",
8083 info2->sharename ));
8086 if ((snum = print_queue_snum(info2->sharename)) == -1) {
8087 return WERR_ACCESS_DENIED;
8090 /* you must be a printer admin to add a new printer */
8091 if (!print_access_check(p->session_info,
8092 p->msg_ctx,
8093 snum,
8094 PRINTER_ACCESS_ADMINISTER)) {
8095 return WERR_ACCESS_DENIED;
8099 * Do sanity check on the requested changes for Samba.
8102 if (!check_printer_ok(p->mem_ctx, info2, snum)) {
8103 return WERR_INVALID_PARAM;
8106 if (devmode == NULL) {
8107 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
8110 err = update_dsspooler(p->mem_ctx,
8111 get_session_info_system(),
8112 p->msg_ctx,
8114 info2,
8115 NULL);
8116 if (!W_ERROR_IS_OK(err)) {
8117 return err;
8120 err = winreg_update_printer_internal(p->mem_ctx,
8121 get_session_info_system(),
8122 p->msg_ctx,
8123 info2->sharename,
8124 info2_mask,
8125 info2,
8126 devmode,
8127 secdesc);
8128 if (!W_ERROR_IS_OK(err)) {
8129 return err;
8132 err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
8133 if (!W_ERROR_IS_OK(err)) {
8134 /* Handle open failed - remove addition. */
8135 ZERO_STRUCTP(handle);
8136 return err;
8139 return WERR_OK;
8142 /****************************************************************
8143 _spoolss_AddPrinterEx
8144 ****************************************************************/
8146 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
8147 struct spoolss_AddPrinterEx *r)
8149 switch (r->in.info_ctr->level) {
8150 case 1:
8151 /* we don't handle yet */
8152 /* but I know what to do ... */
8153 return WERR_UNKNOWN_LEVEL;
8154 case 2:
8155 return spoolss_addprinterex_level_2(p, r->in.server,
8156 r->in.info_ctr,
8157 r->in.devmode_ctr->devmode,
8158 r->in.secdesc_ctr->sd,
8159 r->in.userlevel_ctr,
8160 r->out.handle);
8161 default:
8162 return WERR_UNKNOWN_LEVEL;
8166 /****************************************************************
8167 _spoolss_AddPrinter
8168 ****************************************************************/
8170 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
8171 struct spoolss_AddPrinter *r)
8173 struct spoolss_AddPrinterEx a;
8174 struct spoolss_UserLevelCtr userlevel_ctr;
8176 ZERO_STRUCT(userlevel_ctr);
8178 userlevel_ctr.level = 1;
8180 a.in.server = r->in.server;
8181 a.in.info_ctr = r->in.info_ctr;
8182 a.in.devmode_ctr = r->in.devmode_ctr;
8183 a.in.secdesc_ctr = r->in.secdesc_ctr;
8184 a.in.userlevel_ctr = &userlevel_ctr;
8185 a.out.handle = r->out.handle;
8187 return _spoolss_AddPrinterEx(p, &a);
8190 /****************************************************************
8191 _spoolss_AddPrinterDriverEx
8192 ****************************************************************/
8194 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
8195 struct spoolss_AddPrinterDriverEx *r)
8197 WERROR err = WERR_OK;
8198 const char *driver_name = NULL;
8199 uint32_t version;
8200 const char *fn;
8202 switch (p->opnum) {
8203 case NDR_SPOOLSS_ADDPRINTERDRIVER:
8204 fn = "_spoolss_AddPrinterDriver";
8205 break;
8206 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
8207 fn = "_spoolss_AddPrinterDriverEx";
8208 break;
8209 default:
8210 return WERR_INVALID_PARAM;
8214 * we only support the semantics of AddPrinterDriver()
8215 * i.e. only copy files that are newer than existing ones
8218 if (r->in.flags == 0) {
8219 return WERR_INVALID_PARAM;
8222 if (r->in.flags != APD_COPY_NEW_FILES) {
8223 return WERR_ACCESS_DENIED;
8226 /* FIXME */
8227 if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
8228 /* Clever hack from Martin Zielinski <mz@seh.de>
8229 * to allow downgrade from level 8 (Vista).
8231 DEBUG(0,("%s: level %d not yet implemented\n", fn,
8232 r->in.info_ctr->level));
8233 return WERR_UNKNOWN_LEVEL;
8236 DEBUG(5,("Cleaning driver's information\n"));
8237 err = clean_up_driver_struct(p->mem_ctx, p->session_info, r->in.info_ctr);
8238 if (!W_ERROR_IS_OK(err))
8239 goto done;
8241 DEBUG(5,("Moving driver to final destination\n"));
8242 err = move_driver_to_download_area(p->session_info, r->in.info_ctr);
8243 if (!W_ERROR_IS_OK(err)) {
8244 goto done;
8247 err = winreg_add_driver_internal(p->mem_ctx,
8248 get_session_info_system(),
8249 p->msg_ctx,
8250 r->in.info_ctr,
8251 &driver_name,
8252 &version);
8253 if (!W_ERROR_IS_OK(err)) {
8254 goto done;
8258 * I think this is where he DrvUpgradePrinter() hook would be
8259 * be called in a driver's interface DLL on a Windows NT 4.0/2k
8260 * server. Right now, we just need to send ourselves a message
8261 * to update each printer bound to this driver. --jerry
8264 if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8265 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8266 fn, driver_name));
8269 done:
8270 return err;
8273 /****************************************************************
8274 _spoolss_AddPrinterDriver
8275 ****************************************************************/
8277 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8278 struct spoolss_AddPrinterDriver *r)
8280 struct spoolss_AddPrinterDriverEx a;
8282 switch (r->in.info_ctr->level) {
8283 case 2:
8284 case 3:
8285 case 4:
8286 case 5:
8287 break;
8288 default:
8289 return WERR_UNKNOWN_LEVEL;
8292 a.in.servername = r->in.servername;
8293 a.in.info_ctr = r->in.info_ctr;
8294 a.in.flags = APD_COPY_NEW_FILES;
8296 return _spoolss_AddPrinterDriverEx(p, &a);
8299 /****************************************************************************
8300 ****************************************************************************/
8302 struct _spoolss_paths {
8303 int type;
8304 const char *share;
8305 const char *dir;
8308 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8310 static const struct _spoolss_paths spoolss_paths[]= {
8311 { SPOOLSS_DRIVER_PATH, "print$", "DRIVERS" },
8312 { SPOOLSS_PRTPROCS_PATH, "prnproc$", "PRTPROCS" }
8315 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8316 const char *servername,
8317 const char *environment,
8318 int component,
8319 char **path)
8321 const char *pservername = NULL;
8322 const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
8323 const char *short_archi;
8325 *path = NULL;
8327 /* environment may be empty */
8328 if (environment && strlen(environment)) {
8329 long_archi = environment;
8332 /* servername may be empty */
8333 if (servername && strlen(servername)) {
8334 pservername = canon_servername(servername);
8336 if (!is_myname_or_ipaddr(pservername)) {
8337 return WERR_INVALID_PARAM;
8341 if (!(short_archi = get_short_archi(long_archi))) {
8342 return WERR_INVALID_ENVIRONMENT;
8345 switch (component) {
8346 case SPOOLSS_PRTPROCS_PATH:
8347 case SPOOLSS_DRIVER_PATH:
8348 if (pservername) {
8349 *path = talloc_asprintf(mem_ctx,
8350 "\\\\%s\\%s\\%s",
8351 pservername,
8352 spoolss_paths[component].share,
8353 short_archi);
8354 } else {
8355 *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8356 SPOOLSS_DEFAULT_SERVER_PATH,
8357 spoolss_paths[component].dir,
8358 short_archi);
8360 break;
8361 default:
8362 return WERR_INVALID_PARAM;
8365 if (!*path) {
8366 return WERR_NOMEM;
8369 return WERR_OK;
8372 /****************************************************************************
8373 ****************************************************************************/
8375 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8376 const char *servername,
8377 const char *environment,
8378 struct spoolss_DriverDirectoryInfo1 *r)
8380 WERROR werr;
8381 char *path = NULL;
8383 werr = compose_spoolss_server_path(mem_ctx,
8384 servername,
8385 environment,
8386 SPOOLSS_DRIVER_PATH,
8387 &path);
8388 if (!W_ERROR_IS_OK(werr)) {
8389 return werr;
8392 DEBUG(4,("printer driver directory: [%s]\n", path));
8394 r->directory_name = path;
8396 return WERR_OK;
8399 /****************************************************************
8400 _spoolss_GetPrinterDriverDirectory
8401 ****************************************************************/
8403 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8404 struct spoolss_GetPrinterDriverDirectory *r)
8406 WERROR werror;
8408 /* that's an [in out] buffer */
8410 if (!r->in.buffer && (r->in.offered != 0)) {
8411 return WERR_INVALID_PARAM;
8414 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8415 r->in.level));
8417 *r->out.needed = 0;
8419 /* r->in.level is ignored */
8421 werror = getprinterdriverdir_level_1(p->mem_ctx,
8422 r->in.server,
8423 r->in.environment,
8424 &r->out.info->info1);
8425 if (!W_ERROR_IS_OK(werror)) {
8426 TALLOC_FREE(r->out.info);
8427 return werror;
8430 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8431 r->out.info, r->in.level);
8432 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8434 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8437 /****************************************************************
8438 _spoolss_EnumPrinterData
8439 ****************************************************************/
8441 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8442 struct spoolss_EnumPrinterData *r)
8444 WERROR result;
8445 struct spoolss_EnumPrinterDataEx r2;
8446 uint32_t count;
8447 struct spoolss_PrinterEnumValues *info, *val = NULL;
8448 uint32_t needed;
8450 r2.in.handle = r->in.handle;
8451 r2.in.key_name = "PrinterDriverData";
8452 r2.in.offered = 0;
8453 r2.out.count = &count;
8454 r2.out.info = &info;
8455 r2.out.needed = &needed;
8457 result = _spoolss_EnumPrinterDataEx(p, &r2);
8458 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8459 r2.in.offered = needed;
8460 result = _spoolss_EnumPrinterDataEx(p, &r2);
8462 if (!W_ERROR_IS_OK(result)) {
8463 return result;
8467 * The NT machine wants to know the biggest size of value and data
8469 * cf: MSDN EnumPrinterData remark section
8472 if (!r->in.value_offered && !r->in.data_offered) {
8473 uint32_t biggest_valuesize = 0;
8474 uint32_t biggest_datasize = 0;
8475 int i, name_length;
8477 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8479 for (i=0; i<count; i++) {
8481 name_length = strlen(info[i].value_name);
8482 if (strlen(info[i].value_name) > biggest_valuesize) {
8483 biggest_valuesize = name_length;
8486 if (info[i].data_length > biggest_datasize) {
8487 biggest_datasize = info[i].data_length;
8490 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8491 biggest_datasize));
8494 /* the value is an UNICODE string but real_value_size is the length
8495 in bytes including the trailing 0 */
8497 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8498 *r->out.data_needed = biggest_datasize;
8500 DEBUG(6,("final values: [%d], [%d]\n",
8501 *r->out.value_needed, *r->out.data_needed));
8503 return WERR_OK;
8506 if (r->in.enum_index < count) {
8507 val = &info[r->in.enum_index];
8510 if (val == NULL) {
8511 /* out_value should default to "" or else NT4 has
8512 problems unmarshalling the response */
8514 if (r->in.value_offered) {
8515 *r->out.value_needed = 1;
8516 r->out.value_name = talloc_strdup(r, "");
8517 if (!r->out.value_name) {
8518 return WERR_NOMEM;
8520 } else {
8521 r->out.value_name = NULL;
8522 *r->out.value_needed = 0;
8525 /* the data is counted in bytes */
8527 *r->out.data_needed = r->in.data_offered;
8529 result = WERR_NO_MORE_ITEMS;
8530 } else {
8532 * the value is:
8533 * - counted in bytes in the request
8534 * - counted in UNICODE chars in the max reply
8535 * - counted in bytes in the real size
8537 * take a pause *before* coding not *during* coding
8540 /* name */
8541 if (r->in.value_offered) {
8542 r->out.value_name = talloc_strdup(r, val->value_name);
8543 if (!r->out.value_name) {
8544 return WERR_NOMEM;
8546 *r->out.value_needed = val->value_name_len;
8547 } else {
8548 r->out.value_name = NULL;
8549 *r->out.value_needed = 0;
8552 /* type */
8554 *r->out.type = val->type;
8556 /* data - counted in bytes */
8559 * See the section "Dynamically Typed Query Parameters"
8560 * in MS-RPRN.
8563 if (r->out.data && val->data && val->data->data &&
8564 val->data_length && r->in.data_offered) {
8565 memcpy(r->out.data, val->data->data,
8566 MIN(val->data_length,r->in.data_offered));
8569 *r->out.data_needed = val->data_length;
8571 result = WERR_OK;
8574 return result;
8577 /****************************************************************
8578 _spoolss_SetPrinterData
8579 ****************************************************************/
8581 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8582 struct spoolss_SetPrinterData *r)
8584 struct spoolss_SetPrinterDataEx r2;
8586 r2.in.handle = r->in.handle;
8587 r2.in.key_name = "PrinterDriverData";
8588 r2.in.value_name = r->in.value_name;
8589 r2.in.type = r->in.type;
8590 r2.in.data = r->in.data;
8591 r2.in.offered = r->in.offered;
8593 return _spoolss_SetPrinterDataEx(p, &r2);
8596 /****************************************************************
8597 _spoolss_ResetPrinter
8598 ****************************************************************/
8600 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8601 struct spoolss_ResetPrinter *r)
8603 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8604 int snum;
8606 DEBUG(5,("_spoolss_ResetPrinter\n"));
8609 * All we do is to check to see if the handle and queue is valid.
8610 * This call really doesn't mean anything to us because we only
8611 * support RAW printing. --jerry
8614 if (!Printer) {
8615 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8616 OUR_HANDLE(r->in.handle)));
8617 return WERR_BADFID;
8620 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8621 return WERR_BADFID;
8624 /* blindly return success */
8625 return WERR_OK;
8628 /****************************************************************
8629 _spoolss_DeletePrinterData
8630 ****************************************************************/
8632 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8633 struct spoolss_DeletePrinterData *r)
8635 struct spoolss_DeletePrinterDataEx r2;
8637 r2.in.handle = r->in.handle;
8638 r2.in.key_name = "PrinterDriverData";
8639 r2.in.value_name = r->in.value_name;
8641 return _spoolss_DeletePrinterDataEx(p, &r2);
8644 /****************************************************************
8645 _spoolss_AddForm
8646 ****************************************************************/
8648 WERROR _spoolss_AddForm(struct pipes_struct *p,
8649 struct spoolss_AddForm *r)
8651 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8652 int snum = -1;
8653 WERROR status = WERR_OK;
8654 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8655 struct dcerpc_binding_handle *b;
8656 TALLOC_CTX *tmp_ctx = NULL;
8658 DEBUG(5,("_spoolss_AddForm\n"));
8660 if (!Printer) {
8661 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8662 OUR_HANDLE(r->in.handle)));
8663 return WERR_BADFID;
8666 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8667 and not a printer admin, then fail */
8669 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8670 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8671 !token_contains_name_in_list(uidtoname(p->session_info->unix_token->uid),
8672 p->session_info->info->domain_name,
8673 NULL,
8674 p->session_info->security_token,
8675 lp_printer_admin(snum))) {
8676 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8677 return WERR_ACCESS_DENIED;
8680 switch (form->flags) {
8681 case SPOOLSS_FORM_USER:
8682 case SPOOLSS_FORM_BUILTIN:
8683 case SPOOLSS_FORM_PRINTER:
8684 break;
8685 default:
8686 return WERR_INVALID_PARAM;
8689 tmp_ctx = talloc_new(p->mem_ctx);
8690 if (!tmp_ctx) {
8691 return WERR_NOMEM;
8694 status = winreg_printer_binding_handle(tmp_ctx,
8695 get_session_info_system(),
8696 p->msg_ctx,
8697 &b);
8698 if (!W_ERROR_IS_OK(status)) {
8699 goto done;
8702 status = winreg_printer_addform1(tmp_ctx, b, form);
8703 if (!W_ERROR_IS_OK(status)) {
8704 goto done;
8708 * ChangeID must always be set if this is a printer
8710 if (Printer->printer_type == SPLHND_PRINTER) {
8711 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8712 status = WERR_BADFID;
8713 goto done;
8716 status = winreg_printer_update_changeid(tmp_ctx, b,
8717 lp_const_servicename(snum));
8720 done:
8721 talloc_free(tmp_ctx);
8722 return status;
8725 /****************************************************************
8726 _spoolss_DeleteForm
8727 ****************************************************************/
8729 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8730 struct spoolss_DeleteForm *r)
8732 const char *form_name = r->in.form_name;
8733 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8734 int snum = -1;
8735 WERROR status = WERR_OK;
8736 struct dcerpc_binding_handle *b;
8737 TALLOC_CTX *tmp_ctx = NULL;
8739 DEBUG(5,("_spoolss_DeleteForm\n"));
8741 if (!Printer) {
8742 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8743 OUR_HANDLE(r->in.handle)));
8744 return WERR_BADFID;
8747 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8748 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8749 !token_contains_name_in_list(uidtoname(p->session_info->unix_token->uid),
8750 p->session_info->info->domain_name,
8751 NULL,
8752 p->session_info->security_token,
8753 lp_printer_admin(snum))) {
8754 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8755 return WERR_ACCESS_DENIED;
8758 tmp_ctx = talloc_new(p->mem_ctx);
8759 if (!tmp_ctx) {
8760 return WERR_NOMEM;
8763 status = winreg_printer_binding_handle(tmp_ctx,
8764 get_session_info_system(),
8765 p->msg_ctx,
8766 &b);
8767 if (!W_ERROR_IS_OK(status)) {
8768 goto done;
8771 status = winreg_printer_deleteform1(tmp_ctx, b, form_name);
8772 if (!W_ERROR_IS_OK(status)) {
8773 goto done;
8777 * ChangeID must always be set if this is a printer
8779 if (Printer->printer_type == SPLHND_PRINTER) {
8780 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8781 status = WERR_BADFID;
8782 goto done;
8785 status = winreg_printer_update_changeid(tmp_ctx, b,
8786 lp_const_servicename(snum));
8789 done:
8790 talloc_free(tmp_ctx);
8791 return status;
8794 /****************************************************************
8795 _spoolss_SetForm
8796 ****************************************************************/
8798 WERROR _spoolss_SetForm(struct pipes_struct *p,
8799 struct spoolss_SetForm *r)
8801 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8802 const char *form_name = r->in.form_name;
8803 int snum = -1;
8804 WERROR status = WERR_OK;
8805 struct dcerpc_binding_handle *b;
8806 TALLOC_CTX *tmp_ctx = NULL;
8808 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8810 DEBUG(5,("_spoolss_SetForm\n"));
8812 if (!Printer) {
8813 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8814 OUR_HANDLE(r->in.handle)));
8815 return WERR_BADFID;
8818 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8819 and not a printer admin, then fail */
8821 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8822 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8823 !token_contains_name_in_list(uidtoname(p->session_info->unix_token->uid),
8824 p->session_info->info->domain_name,
8825 NULL,
8826 p->session_info->security_token,
8827 lp_printer_admin(snum))) {
8828 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8829 return WERR_ACCESS_DENIED;
8832 tmp_ctx = talloc_new(p->mem_ctx);
8833 if (!tmp_ctx) {
8834 return WERR_NOMEM;
8837 status = winreg_printer_binding_handle(tmp_ctx,
8838 get_session_info_system(),
8839 p->msg_ctx,
8840 &b);
8841 if (!W_ERROR_IS_OK(status)) {
8842 goto done;
8845 status = winreg_printer_setform1(tmp_ctx, b,
8846 form_name,
8847 form);
8848 if (!W_ERROR_IS_OK(status)) {
8849 goto done;
8853 * ChangeID must always be set if this is a printer
8855 if (Printer->printer_type == SPLHND_PRINTER) {
8856 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8857 status = WERR_BADFID;
8858 goto done;
8861 status = winreg_printer_update_changeid(tmp_ctx, b,
8862 lp_const_servicename(snum));
8865 done:
8866 talloc_free(tmp_ctx);
8867 return status;
8870 /****************************************************************************
8871 fill_print_processor1
8872 ****************************************************************************/
8874 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8875 struct spoolss_PrintProcessorInfo1 *r,
8876 const char *print_processor_name)
8878 r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8879 W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8881 return WERR_OK;
8884 /****************************************************************************
8885 enumprintprocessors level 1.
8886 ****************************************************************************/
8888 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8889 union spoolss_PrintProcessorInfo **info_p,
8890 uint32_t *count)
8892 union spoolss_PrintProcessorInfo *info;
8893 WERROR result;
8895 info = talloc_array(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8896 W_ERROR_HAVE_NO_MEMORY(info);
8898 *count = 1;
8900 result = fill_print_processor1(info, &info[0].info1, "winprint");
8901 if (!W_ERROR_IS_OK(result)) {
8902 goto out;
8905 out:
8906 if (!W_ERROR_IS_OK(result)) {
8907 TALLOC_FREE(info);
8908 *count = 0;
8909 return result;
8912 *info_p = info;
8914 return WERR_OK;
8917 /****************************************************************
8918 _spoolss_EnumPrintProcessors
8919 ****************************************************************/
8921 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
8922 struct spoolss_EnumPrintProcessors *r)
8924 WERROR result;
8926 /* that's an [in out] buffer */
8928 if (!r->in.buffer && (r->in.offered != 0)) {
8929 return WERR_INVALID_PARAM;
8932 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8935 * Enumerate the print processors ...
8937 * Just reply with "winprint", to keep NT happy
8938 * and I can use my nice printer checker.
8941 *r->out.count = 0;
8942 *r->out.needed = 0;
8943 *r->out.info = NULL;
8945 if (!get_short_archi(r->in.environment)) {
8946 return WERR_INVALID_ENVIRONMENT;
8949 switch (r->in.level) {
8950 case 1:
8951 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8952 r->out.count);
8953 break;
8954 default:
8955 return WERR_UNKNOWN_LEVEL;
8958 if (!W_ERROR_IS_OK(result)) {
8959 return result;
8962 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8963 spoolss_EnumPrintProcessors,
8964 *r->out.info, r->in.level,
8965 *r->out.count);
8966 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8967 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8969 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8972 /****************************************************************************
8973 fill_printprocdatatype1
8974 ****************************************************************************/
8976 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8977 struct spoolss_PrintProcDataTypesInfo1 *r,
8978 const char *name_array)
8980 r->name_array = talloc_strdup(mem_ctx, name_array);
8981 W_ERROR_HAVE_NO_MEMORY(r->name_array);
8983 return WERR_OK;
8986 /****************************************************************************
8987 enumprintprocdatatypes level 1.
8988 ****************************************************************************/
8990 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8991 union spoolss_PrintProcDataTypesInfo **info_p,
8992 uint32_t *count)
8994 WERROR result;
8995 union spoolss_PrintProcDataTypesInfo *info;
8997 info = talloc_array(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8998 W_ERROR_HAVE_NO_MEMORY(info);
9000 *count = 1;
9002 result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
9003 if (!W_ERROR_IS_OK(result)) {
9004 goto out;
9007 out:
9008 if (!W_ERROR_IS_OK(result)) {
9009 TALLOC_FREE(info);
9010 *count = 0;
9011 return result;
9014 *info_p = info;
9016 return WERR_OK;
9019 /****************************************************************
9020 _spoolss_EnumPrintProcDataTypes
9021 ****************************************************************/
9023 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
9024 struct spoolss_EnumPrintProcDataTypes *r)
9026 WERROR result;
9028 /* that's an [in out] buffer */
9030 if (!r->in.buffer && (r->in.offered != 0)) {
9031 return WERR_INVALID_PARAM;
9034 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
9036 *r->out.count = 0;
9037 *r->out.needed = 0;
9038 *r->out.info = NULL;
9040 if (r->in.print_processor_name == NULL ||
9041 !strequal(r->in.print_processor_name, "winprint")) {
9042 return WERR_UNKNOWN_PRINTPROCESSOR;
9045 switch (r->in.level) {
9046 case 1:
9047 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
9048 r->out.count);
9049 break;
9050 default:
9051 return WERR_UNKNOWN_LEVEL;
9054 if (!W_ERROR_IS_OK(result)) {
9055 return result;
9058 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9059 spoolss_EnumPrintProcDataTypes,
9060 *r->out.info, r->in.level,
9061 *r->out.count);
9062 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9063 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9065 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9068 /****************************************************************************
9069 fill_monitor_1
9070 ****************************************************************************/
9072 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
9073 struct spoolss_MonitorInfo1 *r,
9074 const char *monitor_name)
9076 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
9077 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9079 return WERR_OK;
9082 /****************************************************************************
9083 fill_monitor_2
9084 ****************************************************************************/
9086 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
9087 struct spoolss_MonitorInfo2 *r,
9088 const char *monitor_name,
9089 const char *environment,
9090 const char *dll_name)
9092 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
9093 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9094 r->environment = talloc_strdup(mem_ctx, environment);
9095 W_ERROR_HAVE_NO_MEMORY(r->environment);
9096 r->dll_name = talloc_strdup(mem_ctx, dll_name);
9097 W_ERROR_HAVE_NO_MEMORY(r->dll_name);
9099 return WERR_OK;
9102 /****************************************************************************
9103 enumprintmonitors level 1.
9104 ****************************************************************************/
9106 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
9107 union spoolss_MonitorInfo **info_p,
9108 uint32_t *count)
9110 union spoolss_MonitorInfo *info;
9111 WERROR result = WERR_OK;
9113 info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9114 W_ERROR_HAVE_NO_MEMORY(info);
9116 *count = 2;
9118 result = fill_monitor_1(info, &info[0].info1,
9119 SPL_LOCAL_PORT);
9120 if (!W_ERROR_IS_OK(result)) {
9121 goto out;
9124 result = fill_monitor_1(info, &info[1].info1,
9125 SPL_TCPIP_PORT);
9126 if (!W_ERROR_IS_OK(result)) {
9127 goto out;
9130 out:
9131 if (!W_ERROR_IS_OK(result)) {
9132 TALLOC_FREE(info);
9133 *count = 0;
9134 return result;
9137 *info_p = info;
9139 return WERR_OK;
9142 /****************************************************************************
9143 enumprintmonitors level 2.
9144 ****************************************************************************/
9146 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
9147 union spoolss_MonitorInfo **info_p,
9148 uint32_t *count)
9150 union spoolss_MonitorInfo *info;
9151 WERROR result = WERR_OK;
9153 info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9154 W_ERROR_HAVE_NO_MEMORY(info);
9156 *count = 2;
9158 result = fill_monitor_2(info, &info[0].info2,
9159 SPL_LOCAL_PORT,
9160 "Windows NT X86", /* FIXME */
9161 "localmon.dll");
9162 if (!W_ERROR_IS_OK(result)) {
9163 goto out;
9166 result = fill_monitor_2(info, &info[1].info2,
9167 SPL_TCPIP_PORT,
9168 "Windows NT X86", /* FIXME */
9169 "tcpmon.dll");
9170 if (!W_ERROR_IS_OK(result)) {
9171 goto out;
9174 out:
9175 if (!W_ERROR_IS_OK(result)) {
9176 TALLOC_FREE(info);
9177 *count = 0;
9178 return result;
9181 *info_p = info;
9183 return WERR_OK;
9186 /****************************************************************
9187 _spoolss_EnumMonitors
9188 ****************************************************************/
9190 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
9191 struct spoolss_EnumMonitors *r)
9193 WERROR result;
9195 /* that's an [in out] buffer */
9197 if (!r->in.buffer && (r->in.offered != 0)) {
9198 return WERR_INVALID_PARAM;
9201 DEBUG(5,("_spoolss_EnumMonitors\n"));
9204 * Enumerate the print monitors ...
9206 * Just reply with "Local Port", to keep NT happy
9207 * and I can use my nice printer checker.
9210 *r->out.count = 0;
9211 *r->out.needed = 0;
9212 *r->out.info = NULL;
9214 switch (r->in.level) {
9215 case 1:
9216 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
9217 r->out.count);
9218 break;
9219 case 2:
9220 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
9221 r->out.count);
9222 break;
9223 default:
9224 return WERR_UNKNOWN_LEVEL;
9227 if (!W_ERROR_IS_OK(result)) {
9228 return result;
9231 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9232 spoolss_EnumMonitors,
9233 *r->out.info, r->in.level,
9234 *r->out.count);
9235 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9236 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9238 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9241 /****************************************************************************
9242 ****************************************************************************/
9244 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
9245 const print_queue_struct *queue,
9246 int count, int snum,
9247 struct spoolss_PrinterInfo2 *pinfo2,
9248 uint32_t jobid,
9249 struct spoolss_JobInfo1 *r)
9251 int i = 0;
9252 bool found = false;
9254 for (i=0; i<count; i++) {
9255 if (queue[i].job == (int)jobid) {
9256 found = true;
9257 break;
9261 if (found == false) {
9262 /* NT treats not found as bad param... yet another bad choice */
9263 return WERR_INVALID_PARAM;
9266 return fill_job_info1(mem_ctx,
9268 &queue[i],
9270 snum,
9271 pinfo2);
9274 /****************************************************************************
9275 ****************************************************************************/
9277 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9278 const print_queue_struct *queue,
9279 int count, int snum,
9280 struct spoolss_PrinterInfo2 *pinfo2,
9281 uint32_t jobid,
9282 struct spoolss_JobInfo2 *r)
9284 int i = 0;
9285 bool found = false;
9286 struct spoolss_DeviceMode *devmode;
9287 WERROR result;
9289 for (i=0; i<count; i++) {
9290 if (queue[i].job == (int)jobid) {
9291 found = true;
9292 break;
9296 if (found == false) {
9297 /* NT treats not found as bad param... yet another bad
9298 choice */
9299 return WERR_INVALID_PARAM;
9303 * if the print job does not have a DEVMODE associated with it,
9304 * just use the one for the printer. A NULL devicemode is not
9305 * a failure condition
9308 devmode = print_job_devmode(lp_const_servicename(snum), jobid);
9309 if (!devmode) {
9310 result = spoolss_create_default_devmode(mem_ctx,
9311 pinfo2->printername,
9312 &devmode);
9313 if (!W_ERROR_IS_OK(result)) {
9314 DEBUG(3, ("Can't proceed w/o a devmode!"));
9315 return result;
9319 return fill_job_info2(mem_ctx,
9321 &queue[i],
9323 snum,
9324 pinfo2,
9325 devmode);
9328 /****************************************************************
9329 _spoolss_GetJob
9330 ****************************************************************/
9332 WERROR _spoolss_GetJob(struct pipes_struct *p,
9333 struct spoolss_GetJob *r)
9335 WERROR result = WERR_OK;
9336 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9337 int snum;
9338 int count;
9339 print_queue_struct *queue = NULL;
9340 print_status_struct prt_status;
9342 /* that's an [in out] buffer */
9344 if (!r->in.buffer && (r->in.offered != 0)) {
9345 return WERR_INVALID_PARAM;
9348 DEBUG(5,("_spoolss_GetJob\n"));
9350 *r->out.needed = 0;
9352 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9353 return WERR_BADFID;
9356 result = winreg_get_printer_internal(p->mem_ctx,
9357 get_session_info_system(),
9358 p->msg_ctx,
9359 lp_const_servicename(snum),
9360 &pinfo2);
9361 if (!W_ERROR_IS_OK(result)) {
9362 return result;
9365 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9367 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9368 count, prt_status.status, prt_status.message));
9370 switch (r->in.level) {
9371 case 1:
9372 result = getjob_level_1(p->mem_ctx,
9373 queue, count, snum, pinfo2,
9374 r->in.job_id, &r->out.info->info1);
9375 break;
9376 case 2:
9377 result = getjob_level_2(p->mem_ctx,
9378 queue, count, snum, pinfo2,
9379 r->in.job_id, &r->out.info->info2);
9380 break;
9381 default:
9382 result = WERR_UNKNOWN_LEVEL;
9383 break;
9386 SAFE_FREE(queue);
9387 TALLOC_FREE(pinfo2);
9389 if (!W_ERROR_IS_OK(result)) {
9390 TALLOC_FREE(r->out.info);
9391 return result;
9394 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9395 r->in.level);
9396 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9398 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9401 /****************************************************************
9402 _spoolss_GetPrinterDataEx
9403 ****************************************************************/
9405 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9406 struct spoolss_GetPrinterDataEx *r)
9409 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9410 const char *printer;
9411 int snum = 0;
9412 WERROR result = WERR_OK;
9413 DATA_BLOB blob;
9414 enum winreg_Type val_type = REG_NONE;
9415 uint8_t *val_data = NULL;
9416 uint32_t val_size = 0;
9417 struct dcerpc_binding_handle *b;
9418 TALLOC_CTX *tmp_ctx;
9420 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9422 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9423 r->in.key_name, r->in.value_name));
9425 /* in case of problem, return some default values */
9427 *r->out.needed = 0;
9428 *r->out.type = REG_NONE;
9430 tmp_ctx = talloc_new(p->mem_ctx);
9431 if (!tmp_ctx) {
9432 return WERR_NOMEM;
9435 if (!Printer) {
9436 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9437 OUR_HANDLE(r->in.handle)));
9438 result = WERR_BADFID;
9439 goto done;
9442 /* check to see if the keyname is valid */
9443 if (!strlen(r->in.key_name)) {
9444 result = WERR_INVALID_PARAM;
9445 goto done;
9448 /* Is the handle to a printer or to the server? */
9450 if (Printer->printer_type == SPLHND_SERVER) {
9452 union spoolss_PrinterData data;
9454 result = getprinterdata_printer_server(tmp_ctx,
9455 r->in.value_name,
9456 r->out.type,
9457 &data);
9458 if (!W_ERROR_IS_OK(result)) {
9459 goto done;
9462 result = push_spoolss_PrinterData(tmp_ctx, &blob,
9463 *r->out.type, &data);
9464 if (!W_ERROR_IS_OK(result)) {
9465 goto done;
9468 *r->out.needed = blob.length;
9470 if (r->in.offered >= *r->out.needed) {
9471 memcpy(r->out.data, blob.data, blob.length);
9474 result = WERR_OK;
9475 goto done;
9478 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9479 result = WERR_BADFID;
9480 goto done;
9482 printer = lp_const_servicename(snum);
9484 result = winreg_printer_binding_handle(tmp_ctx,
9485 get_session_info_system(),
9486 p->msg_ctx,
9487 &b);
9488 if (!W_ERROR_IS_OK(result)) {
9489 goto done;
9492 /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9493 if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9494 strequal(r->in.value_name, "ChangeId")) {
9495 *r->out.type = REG_DWORD;
9496 *r->out.needed = 4;
9497 if (r->in.offered >= *r->out.needed) {
9498 uint32_t changeid = 0;
9500 result = winreg_printer_get_changeid(tmp_ctx, b,
9501 printer,
9502 &changeid);
9503 if (!W_ERROR_IS_OK(result)) {
9504 goto done;
9507 SIVAL(r->out.data, 0, changeid);
9508 result = WERR_OK;
9510 goto done;
9513 result = winreg_get_printer_dataex(tmp_ctx, b,
9514 printer,
9515 r->in.key_name,
9516 r->in.value_name,
9517 &val_type,
9518 &val_data,
9519 &val_size);
9520 if (!W_ERROR_IS_OK(result)) {
9521 goto done;
9524 *r->out.needed = val_size;
9525 *r->out.type = val_type;
9527 if (r->in.offered >= *r->out.needed) {
9528 memcpy(r->out.data, val_data, val_size);
9531 done:
9532 /* NOTE: do not replace type when returning WERR_MORE_DATA */
9534 if (W_ERROR_IS_OK(result)) {
9535 result = SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9538 talloc_free(tmp_ctx);
9539 return result;
9542 /****************************************************************
9543 _spoolss_SetPrinterDataEx
9544 ****************************************************************/
9546 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9547 struct spoolss_SetPrinterDataEx *r)
9549 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9550 int snum = 0;
9551 WERROR result = WERR_OK;
9552 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9553 char *oid_string;
9554 struct dcerpc_binding_handle *b;
9555 TALLOC_CTX *tmp_ctx;
9557 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9559 /* From MSDN documentation of SetPrinterDataEx: pass request to
9560 SetPrinterData if key is "PrinterDriverData" */
9562 if (!Printer) {
9563 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9564 OUR_HANDLE(r->in.handle)));
9565 return WERR_BADFID;
9568 if (Printer->printer_type == SPLHND_SERVER) {
9569 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9570 "Not implemented for server handles yet\n"));
9571 return WERR_INVALID_PARAM;
9574 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9575 return WERR_BADFID;
9579 * Access check : NT returns "access denied" if you make a
9580 * SetPrinterData call without the necessary privildge.
9581 * we were originally returning OK if nothing changed
9582 * which made Win2k issue **a lot** of SetPrinterData
9583 * when connecting to a printer --jerry
9586 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9587 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9588 "change denied by handle access permissions\n"));
9589 return WERR_ACCESS_DENIED;
9592 tmp_ctx = talloc_new(p->mem_ctx);
9593 if (!tmp_ctx) {
9594 return WERR_NOMEM;
9597 result = winreg_printer_binding_handle(tmp_ctx,
9598 get_session_info_system(),
9599 p->msg_ctx,
9600 &b);
9601 if (!W_ERROR_IS_OK(result)) {
9602 goto done;
9605 result = winreg_get_printer(tmp_ctx, b,
9606 lp_servicename(snum),
9607 &pinfo2);
9608 if (!W_ERROR_IS_OK(result)) {
9609 goto done;
9612 /* check for OID in valuename */
9614 oid_string = strchr(r->in.value_name, ',');
9615 if (oid_string) {
9616 *oid_string = '\0';
9617 oid_string++;
9620 /* save the registry data */
9622 result = winreg_set_printer_dataex(tmp_ctx, b,
9623 pinfo2->sharename,
9624 r->in.key_name,
9625 r->in.value_name,
9626 r->in.type,
9627 r->in.data,
9628 r->in.offered);
9630 if (W_ERROR_IS_OK(result)) {
9631 /* save the OID if one was specified */
9632 if (oid_string) {
9633 char *str = talloc_asprintf(tmp_ctx, "%s\\%s",
9634 r->in.key_name, SPOOL_OID_KEY);
9635 if (!str) {
9636 result = WERR_NOMEM;
9637 goto done;
9641 * I'm not checking the status here on purpose. Don't know
9642 * if this is right, but I'm returning the status from the
9643 * previous set_printer_dataex() call. I have no idea if
9644 * this is right. --jerry
9646 winreg_set_printer_dataex(tmp_ctx, b,
9647 pinfo2->sharename,
9648 str,
9649 r->in.value_name,
9650 REG_SZ,
9651 (uint8_t *) oid_string,
9652 strlen(oid_string) + 1);
9655 result = winreg_printer_update_changeid(tmp_ctx, b,
9656 lp_const_servicename(snum));
9660 done:
9661 talloc_free(tmp_ctx);
9662 return result;
9665 /****************************************************************
9666 _spoolss_DeletePrinterDataEx
9667 ****************************************************************/
9669 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9670 struct spoolss_DeletePrinterDataEx *r)
9672 const char *printer;
9673 int snum=0;
9674 WERROR status = WERR_OK;
9675 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9677 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9679 if (!Printer) {
9680 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9681 "Invalid handle (%s:%u:%u).\n",
9682 OUR_HANDLE(r->in.handle)));
9683 return WERR_BADFID;
9686 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9687 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9688 "printer properties change denied by handle\n"));
9689 return WERR_ACCESS_DENIED;
9692 if (!r->in.value_name || !r->in.key_name) {
9693 return WERR_NOMEM;
9696 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9697 return WERR_BADFID;
9699 printer = lp_const_servicename(snum);
9701 status = winreg_delete_printer_dataex_internal(p->mem_ctx,
9702 get_session_info_system(),
9703 p->msg_ctx,
9704 printer,
9705 r->in.key_name,
9706 r->in.value_name);
9707 if (W_ERROR_IS_OK(status)) {
9708 status = winreg_printer_update_changeid_internal(p->mem_ctx,
9709 get_session_info_system(),
9710 p->msg_ctx,
9711 printer);
9714 return status;
9717 /****************************************************************
9718 _spoolss_EnumPrinterKey
9719 ****************************************************************/
9721 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9722 struct spoolss_EnumPrinterKey *r)
9724 uint32_t num_keys;
9725 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9726 int snum = 0;
9727 WERROR result = WERR_BADFILE;
9728 const char **array = NULL;
9729 DATA_BLOB blob;
9731 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9733 if (!Printer) {
9734 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9735 OUR_HANDLE(r->in.handle)));
9736 return WERR_BADFID;
9739 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9740 return WERR_BADFID;
9743 result = winreg_enum_printer_key_internal(p->mem_ctx,
9744 get_session_info_system(),
9745 p->msg_ctx,
9746 lp_const_servicename(snum),
9747 r->in.key_name,
9748 &num_keys,
9749 &array);
9750 if (!W_ERROR_IS_OK(result)) {
9751 goto done;
9754 if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9755 result = WERR_NOMEM;
9756 goto done;
9759 *r->out._ndr_size = r->in.offered / 2;
9760 *r->out.needed = blob.length;
9762 if (r->in.offered < *r->out.needed) {
9763 result = WERR_MORE_DATA;
9764 } else {
9765 result = WERR_OK;
9766 r->out.key_buffer->string_array = array;
9769 done:
9770 if (!W_ERROR_IS_OK(result)) {
9771 TALLOC_FREE(array);
9772 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9773 *r->out.needed = 0;
9777 return result;
9780 /****************************************************************
9781 _spoolss_DeletePrinterKey
9782 ****************************************************************/
9784 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9785 struct spoolss_DeletePrinterKey *r)
9787 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9788 int snum=0;
9789 WERROR status;
9790 const char *printer;
9791 struct dcerpc_binding_handle *b;
9792 TALLOC_CTX *tmp_ctx;
9794 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9796 if (!Printer) {
9797 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9798 OUR_HANDLE(r->in.handle)));
9799 return WERR_BADFID;
9802 /* if keyname == NULL, return error */
9803 if ( !r->in.key_name )
9804 return WERR_INVALID_PARAM;
9806 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9807 return WERR_BADFID;
9810 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9811 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9812 "printer properties change denied by handle\n"));
9813 return WERR_ACCESS_DENIED;
9816 printer = lp_const_servicename(snum);
9818 tmp_ctx = talloc_new(p->mem_ctx);
9819 if (!tmp_ctx) {
9820 return WERR_NOMEM;
9823 status = winreg_printer_binding_handle(tmp_ctx,
9824 get_session_info_system(),
9825 p->msg_ctx,
9826 &b);
9827 if (!W_ERROR_IS_OK(status)) {
9828 goto done;
9831 /* delete the key and all subkeys */
9832 status = winreg_delete_printer_key(tmp_ctx, b,
9833 printer,
9834 r->in.key_name);
9835 if (W_ERROR_IS_OK(status)) {
9836 status = winreg_printer_update_changeid(tmp_ctx, b,
9837 printer);
9840 done:
9841 talloc_free(tmp_ctx);
9842 return status;
9845 /****************************************************************
9846 _spoolss_EnumPrinterDataEx
9847 ****************************************************************/
9849 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
9850 struct spoolss_EnumPrinterDataEx *r)
9852 uint32_t count = 0;
9853 struct spoolss_PrinterEnumValues *info = NULL;
9854 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9855 int snum;
9856 WERROR result;
9858 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9860 *r->out.count = 0;
9861 *r->out.needed = 0;
9862 *r->out.info = NULL;
9864 if (!Printer) {
9865 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9866 OUR_HANDLE(r->in.handle)));
9867 return WERR_BADFID;
9871 * first check for a keyname of NULL or "". Win2k seems to send
9872 * this a lot and we should send back WERR_INVALID_PARAM
9873 * no need to spend time looking up the printer in this case.
9874 * --jerry
9877 if (!strlen(r->in.key_name)) {
9878 result = WERR_INVALID_PARAM;
9879 goto done;
9882 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9883 return WERR_BADFID;
9886 /* now look for a match on the key name */
9887 result = winreg_enum_printer_dataex_internal(p->mem_ctx,
9888 get_session_info_system(),
9889 p->msg_ctx,
9890 lp_const_servicename(snum),
9891 r->in.key_name,
9892 &count,
9893 &info);
9894 if (!W_ERROR_IS_OK(result)) {
9895 goto done;
9898 #if 0 /* FIXME - gd */
9899 /* housekeeping information in the reply */
9901 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9902 * the hand marshalled container size is a multiple
9903 * of 4 bytes for RPC alignment.
9906 if (needed % 4) {
9907 needed += 4-(needed % 4);
9909 #endif
9910 *r->out.count = count;
9911 *r->out.info = info;
9913 done:
9914 if (!W_ERROR_IS_OK(result)) {
9915 return result;
9918 *r->out.needed = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9919 spoolss_EnumPrinterDataEx,
9920 *r->out.info,
9921 *r->out.count);
9922 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9923 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9925 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9928 /****************************************************************************
9929 ****************************************************************************/
9931 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9932 const char *servername,
9933 const char *environment,
9934 struct spoolss_PrintProcessorDirectoryInfo1 *r)
9936 WERROR werr;
9937 char *path = NULL;
9939 werr = compose_spoolss_server_path(mem_ctx,
9940 servername,
9941 environment,
9942 SPOOLSS_PRTPROCS_PATH,
9943 &path);
9944 if (!W_ERROR_IS_OK(werr)) {
9945 return werr;
9948 DEBUG(4,("print processor directory: [%s]\n", path));
9950 r->directory_name = path;
9952 return WERR_OK;
9955 /****************************************************************
9956 _spoolss_GetPrintProcessorDirectory
9957 ****************************************************************/
9959 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
9960 struct spoolss_GetPrintProcessorDirectory *r)
9962 WERROR result;
9963 char *prnproc_share = NULL;
9964 bool prnproc_share_exists = false;
9965 int snum;
9967 /* that's an [in out] buffer */
9969 if (!r->in.buffer && (r->in.offered != 0)) {
9970 return WERR_INVALID_PARAM;
9973 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9974 r->in.level));
9976 *r->out.needed = 0;
9978 /* r->in.level is ignored */
9980 /* We always should reply with a local print processor directory so that
9981 * users are not forced to have a [prnproc$] share on the Samba spoolss
9982 * server, if users decide to do so, lets announce it though - Guenther */
9984 snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
9985 if (!prnproc_share) {
9986 return WERR_NOMEM;
9988 if (snum != -1) {
9989 prnproc_share_exists = true;
9992 result = getprintprocessordirectory_level_1(p->mem_ctx,
9993 prnproc_share_exists ? r->in.server : NULL,
9994 r->in.environment,
9995 &r->out.info->info1);
9996 if (!W_ERROR_IS_OK(result)) {
9997 TALLOC_FREE(r->out.info);
9998 return result;
10001 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
10002 r->out.info, r->in.level);
10003 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
10005 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
10008 /*******************************************************************
10009 ********************************************************************/
10011 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
10012 const char *dllname)
10014 enum ndr_err_code ndr_err;
10015 struct spoolss_MonitorUi ui;
10017 ui.dll_name = dllname;
10019 ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
10020 (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
10021 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10022 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
10024 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10027 /*******************************************************************
10028 Streams the monitor UI DLL name in UNICODE
10029 *******************************************************************/
10031 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
10032 struct security_token *token, DATA_BLOB *in,
10033 DATA_BLOB *out, uint32_t *needed)
10035 const char *dllname = "tcpmonui.dll";
10037 *needed = (strlen(dllname)+1) * 2;
10039 if (out->length < *needed) {
10040 return WERR_INSUFFICIENT_BUFFER;
10043 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10044 return WERR_NOMEM;
10047 return WERR_OK;
10050 /*******************************************************************
10051 ********************************************************************/
10053 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
10054 struct spoolss_PortData1 *port1,
10055 const DATA_BLOB *buf)
10057 enum ndr_err_code ndr_err;
10058 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
10059 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
10060 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10061 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
10063 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10066 /*******************************************************************
10067 ********************************************************************/
10069 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
10070 struct spoolss_PortData2 *port2,
10071 const DATA_BLOB *buf)
10073 enum ndr_err_code ndr_err;
10074 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
10075 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
10076 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10077 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
10079 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10082 /*******************************************************************
10083 Create a new TCP/IP port
10084 *******************************************************************/
10086 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
10087 struct security_token *token, DATA_BLOB *in,
10088 DATA_BLOB *out, uint32_t *needed)
10090 struct spoolss_PortData1 port1;
10091 struct spoolss_PortData2 port2;
10092 char *device_uri = NULL;
10093 uint32_t version;
10095 const char *portname;
10096 const char *hostaddress;
10097 const char *queue;
10098 uint32_t port_number;
10099 uint32_t protocol;
10101 /* peek for spoolss_PortData version */
10103 if (!in || (in->length < (128 + 4))) {
10104 return WERR_GENERAL_FAILURE;
10107 version = IVAL(in->data, 128);
10109 switch (version) {
10110 case 1:
10111 ZERO_STRUCT(port1);
10113 if (!pull_port_data_1(mem_ctx, &port1, in)) {
10114 return WERR_NOMEM;
10117 portname = port1.portname;
10118 hostaddress = port1.hostaddress;
10119 queue = port1.queue;
10120 protocol = port1.protocol;
10121 port_number = port1.port_number;
10123 break;
10124 case 2:
10125 ZERO_STRUCT(port2);
10127 if (!pull_port_data_2(mem_ctx, &port2, in)) {
10128 return WERR_NOMEM;
10131 portname = port2.portname;
10132 hostaddress = port2.hostaddress;
10133 queue = port2.queue;
10134 protocol = port2.protocol;
10135 port_number = port2.port_number;
10137 break;
10138 default:
10139 DEBUG(1,("xcvtcp_addport: "
10140 "unknown version of port_data: %d\n", version));
10141 return WERR_UNKNOWN_PORT;
10144 /* create the device URI and call the add_port_hook() */
10146 switch (protocol) {
10147 case PROTOCOL_RAWTCP_TYPE:
10148 device_uri = talloc_asprintf(mem_ctx,
10149 "socket://%s:%d/", hostaddress,
10150 port_number);
10151 break;
10153 case PROTOCOL_LPR_TYPE:
10154 device_uri = talloc_asprintf(mem_ctx,
10155 "lpr://%s/%s", hostaddress, queue );
10156 break;
10158 default:
10159 return WERR_UNKNOWN_PORT;
10162 if (!device_uri) {
10163 return WERR_NOMEM;
10166 return add_port_hook(mem_ctx, token, portname, device_uri);
10169 /*******************************************************************
10170 *******************************************************************/
10172 struct xcv_api_table xcvtcp_cmds[] = {
10173 { "MonitorUI", xcvtcp_monitorui },
10174 { "AddPort", xcvtcp_addport},
10175 { NULL, NULL }
10178 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
10179 struct security_token *token, const char *command,
10180 DATA_BLOB *inbuf,
10181 DATA_BLOB *outbuf,
10182 uint32_t *needed )
10184 int i;
10186 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
10188 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
10189 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
10190 return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10193 return WERR_BADFUNC;
10196 /*******************************************************************
10197 *******************************************************************/
10198 #if 0 /* don't support management using the "Local Port" monitor */
10200 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
10201 struct security_token *token, DATA_BLOB *in,
10202 DATA_BLOB *out, uint32_t *needed)
10204 const char *dllname = "localui.dll";
10206 *needed = (strlen(dllname)+1) * 2;
10208 if (out->length < *needed) {
10209 return WERR_INSUFFICIENT_BUFFER;
10212 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10213 return WERR_NOMEM;
10216 return WERR_OK;
10219 /*******************************************************************
10220 *******************************************************************/
10222 struct xcv_api_table xcvlocal_cmds[] = {
10223 { "MonitorUI", xcvlocal_monitorui },
10224 { NULL, NULL }
10226 #else
10227 struct xcv_api_table xcvlocal_cmds[] = {
10228 { NULL, NULL }
10230 #endif
10234 /*******************************************************************
10235 *******************************************************************/
10237 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
10238 struct security_token *token, const char *command,
10239 DATA_BLOB *inbuf, DATA_BLOB *outbuf,
10240 uint32_t *needed)
10242 int i;
10244 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10246 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10247 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10248 return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10250 return WERR_BADFUNC;
10253 /****************************************************************
10254 _spoolss_XcvData
10255 ****************************************************************/
10257 WERROR _spoolss_XcvData(struct pipes_struct *p,
10258 struct spoolss_XcvData *r)
10260 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10261 DATA_BLOB out_data = data_blob_null;
10262 WERROR werror;
10264 if (!Printer) {
10265 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10266 OUR_HANDLE(r->in.handle)));
10267 return WERR_BADFID;
10270 /* Has to be a handle to the TCP/IP port monitor */
10272 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10273 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10274 return WERR_BADFID;
10277 /* requires administrative access to the server */
10279 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10280 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10281 return WERR_ACCESS_DENIED;
10284 /* Allocate the outgoing buffer */
10286 if (r->in.out_data_size) {
10287 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10288 if (out_data.data == NULL) {
10289 return WERR_NOMEM;
10293 switch ( Printer->printer_type ) {
10294 case SPLHND_PORTMON_TCP:
10295 werror = process_xcvtcp_command(p->mem_ctx,
10296 p->session_info->security_token,
10297 r->in.function_name,
10298 &r->in.in_data, &out_data,
10299 r->out.needed);
10300 break;
10301 case SPLHND_PORTMON_LOCAL:
10302 werror = process_xcvlocal_command(p->mem_ctx,
10303 p->session_info->security_token,
10304 r->in.function_name,
10305 &r->in.in_data, &out_data,
10306 r->out.needed);
10307 break;
10308 default:
10309 werror = WERR_INVALID_PRINT_MONITOR;
10312 if (!W_ERROR_IS_OK(werror)) {
10313 return werror;
10316 *r->out.status_code = 0;
10318 if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10319 memcpy(r->out.out_data, out_data.data,
10320 MIN(r->in.out_data_size, out_data.length));
10323 return WERR_OK;
10326 /****************************************************************
10327 _spoolss_AddPrintProcessor
10328 ****************************************************************/
10330 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10331 struct spoolss_AddPrintProcessor *r)
10333 /* for now, just indicate success and ignore the add. We'll
10334 automatically set the winprint processor for printer
10335 entries later. Used to debug the LexMark Optra S 1855 PCL
10336 driver --jerry */
10338 return WERR_OK;
10341 /****************************************************************
10342 _spoolss_AddPort
10343 ****************************************************************/
10345 WERROR _spoolss_AddPort(struct pipes_struct *p,
10346 struct spoolss_AddPort *r)
10348 /* do what w2k3 does */
10350 return WERR_NOT_SUPPORTED;
10353 /****************************************************************
10354 _spoolss_GetPrinterDriver
10355 ****************************************************************/
10357 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10358 struct spoolss_GetPrinterDriver *r)
10360 p->rng_fault_state = true;
10361 return WERR_NOT_SUPPORTED;
10364 /****************************************************************
10365 _spoolss_ReadPrinter
10366 ****************************************************************/
10368 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10369 struct spoolss_ReadPrinter *r)
10371 p->rng_fault_state = true;
10372 return WERR_NOT_SUPPORTED;
10375 /****************************************************************
10376 _spoolss_WaitForPrinterChange
10377 ****************************************************************/
10379 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10380 struct spoolss_WaitForPrinterChange *r)
10382 p->rng_fault_state = true;
10383 return WERR_NOT_SUPPORTED;
10386 /****************************************************************
10387 _spoolss_ConfigurePort
10388 ****************************************************************/
10390 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10391 struct spoolss_ConfigurePort *r)
10393 p->rng_fault_state = true;
10394 return WERR_NOT_SUPPORTED;
10397 /****************************************************************
10398 _spoolss_DeletePort
10399 ****************************************************************/
10401 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10402 struct spoolss_DeletePort *r)
10404 p->rng_fault_state = true;
10405 return WERR_NOT_SUPPORTED;
10408 /****************************************************************
10409 _spoolss_CreatePrinterIC
10410 ****************************************************************/
10412 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10413 struct spoolss_CreatePrinterIC *r)
10415 p->rng_fault_state = true;
10416 return WERR_NOT_SUPPORTED;
10419 /****************************************************************
10420 _spoolss_PlayGDIScriptOnPrinterIC
10421 ****************************************************************/
10423 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10424 struct spoolss_PlayGDIScriptOnPrinterIC *r)
10426 p->rng_fault_state = true;
10427 return WERR_NOT_SUPPORTED;
10430 /****************************************************************
10431 _spoolss_DeletePrinterIC
10432 ****************************************************************/
10434 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10435 struct spoolss_DeletePrinterIC *r)
10437 p->rng_fault_state = true;
10438 return WERR_NOT_SUPPORTED;
10441 /****************************************************************
10442 _spoolss_AddPrinterConnection
10443 ****************************************************************/
10445 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10446 struct spoolss_AddPrinterConnection *r)
10448 p->rng_fault_state = true;
10449 return WERR_NOT_SUPPORTED;
10452 /****************************************************************
10453 _spoolss_DeletePrinterConnection
10454 ****************************************************************/
10456 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10457 struct spoolss_DeletePrinterConnection *r)
10459 p->rng_fault_state = true;
10460 return WERR_NOT_SUPPORTED;
10463 /****************************************************************
10464 _spoolss_PrinterMessageBox
10465 ****************************************************************/
10467 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10468 struct spoolss_PrinterMessageBox *r)
10470 p->rng_fault_state = true;
10471 return WERR_NOT_SUPPORTED;
10474 /****************************************************************
10475 _spoolss_AddMonitor
10476 ****************************************************************/
10478 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10479 struct spoolss_AddMonitor *r)
10481 p->rng_fault_state = true;
10482 return WERR_NOT_SUPPORTED;
10485 /****************************************************************
10486 _spoolss_DeleteMonitor
10487 ****************************************************************/
10489 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10490 struct spoolss_DeleteMonitor *r)
10492 p->rng_fault_state = true;
10493 return WERR_NOT_SUPPORTED;
10496 /****************************************************************
10497 _spoolss_DeletePrintProcessor
10498 ****************************************************************/
10500 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10501 struct spoolss_DeletePrintProcessor *r)
10503 p->rng_fault_state = true;
10504 return WERR_NOT_SUPPORTED;
10507 /****************************************************************
10508 _spoolss_AddPrintProvidor
10509 ****************************************************************/
10511 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10512 struct spoolss_AddPrintProvidor *r)
10514 p->rng_fault_state = true;
10515 return WERR_NOT_SUPPORTED;
10518 /****************************************************************
10519 _spoolss_DeletePrintProvidor
10520 ****************************************************************/
10522 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10523 struct spoolss_DeletePrintProvidor *r)
10525 p->rng_fault_state = true;
10526 return WERR_NOT_SUPPORTED;
10529 /****************************************************************
10530 _spoolss_FindFirstPrinterChangeNotification
10531 ****************************************************************/
10533 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10534 struct spoolss_FindFirstPrinterChangeNotification *r)
10536 p->rng_fault_state = true;
10537 return WERR_NOT_SUPPORTED;
10540 /****************************************************************
10541 _spoolss_FindNextPrinterChangeNotification
10542 ****************************************************************/
10544 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10545 struct spoolss_FindNextPrinterChangeNotification *r)
10547 p->rng_fault_state = true;
10548 return WERR_NOT_SUPPORTED;
10551 /****************************************************************
10552 _spoolss_RouterFindFirstPrinterChangeNotificationOld
10553 ****************************************************************/
10555 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10556 struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10558 p->rng_fault_state = true;
10559 return WERR_NOT_SUPPORTED;
10562 /****************************************************************
10563 _spoolss_ReplyOpenPrinter
10564 ****************************************************************/
10566 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10567 struct spoolss_ReplyOpenPrinter *r)
10569 p->rng_fault_state = true;
10570 return WERR_NOT_SUPPORTED;
10573 /****************************************************************
10574 _spoolss_RouterReplyPrinter
10575 ****************************************************************/
10577 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10578 struct spoolss_RouterReplyPrinter *r)
10580 p->rng_fault_state = true;
10581 return WERR_NOT_SUPPORTED;
10584 /****************************************************************
10585 _spoolss_ReplyClosePrinter
10586 ****************************************************************/
10588 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10589 struct spoolss_ReplyClosePrinter *r)
10591 p->rng_fault_state = true;
10592 return WERR_NOT_SUPPORTED;
10595 /****************************************************************
10596 _spoolss_AddPortEx
10597 ****************************************************************/
10599 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10600 struct spoolss_AddPortEx *r)
10602 p->rng_fault_state = true;
10603 return WERR_NOT_SUPPORTED;
10606 /****************************************************************
10607 _spoolss_RouterFindFirstPrinterChangeNotification
10608 ****************************************************************/
10610 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10611 struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10613 p->rng_fault_state = true;
10614 return WERR_NOT_SUPPORTED;
10617 /****************************************************************
10618 _spoolss_SpoolerInit
10619 ****************************************************************/
10621 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10622 struct spoolss_SpoolerInit *r)
10624 p->rng_fault_state = true;
10625 return WERR_NOT_SUPPORTED;
10628 /****************************************************************
10629 _spoolss_ResetPrinterEx
10630 ****************************************************************/
10632 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10633 struct spoolss_ResetPrinterEx *r)
10635 p->rng_fault_state = true;
10636 return WERR_NOT_SUPPORTED;
10639 /****************************************************************
10640 _spoolss_RouterReplyPrinterEx
10641 ****************************************************************/
10643 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10644 struct spoolss_RouterReplyPrinterEx *r)
10646 p->rng_fault_state = true;
10647 return WERR_NOT_SUPPORTED;
10650 /****************************************************************
10651 _spoolss_44
10652 ****************************************************************/
10654 WERROR _spoolss_44(struct pipes_struct *p,
10655 struct spoolss_44 *r)
10657 p->rng_fault_state = true;
10658 return WERR_NOT_SUPPORTED;
10661 /****************************************************************
10662 _spoolss_SetPort
10663 ****************************************************************/
10665 WERROR _spoolss_SetPort(struct pipes_struct *p,
10666 struct spoolss_SetPort *r)
10668 p->rng_fault_state = true;
10669 return WERR_NOT_SUPPORTED;
10672 /****************************************************************
10673 _spoolss_4a
10674 ****************************************************************/
10676 WERROR _spoolss_4a(struct pipes_struct *p,
10677 struct spoolss_4a *r)
10679 p->rng_fault_state = true;
10680 return WERR_NOT_SUPPORTED;
10683 /****************************************************************
10684 _spoolss_4b
10685 ****************************************************************/
10687 WERROR _spoolss_4b(struct pipes_struct *p,
10688 struct spoolss_4b *r)
10690 p->rng_fault_state = true;
10691 return WERR_NOT_SUPPORTED;
10694 /****************************************************************
10695 _spoolss_4c
10696 ****************************************************************/
10698 WERROR _spoolss_4c(struct pipes_struct *p,
10699 struct spoolss_4c *r)
10701 p->rng_fault_state = true;
10702 return WERR_NOT_SUPPORTED;
10705 /****************************************************************
10706 _spoolss_53
10707 ****************************************************************/
10709 WERROR _spoolss_53(struct pipes_struct *p,
10710 struct spoolss_53 *r)
10712 p->rng_fault_state = true;
10713 return WERR_NOT_SUPPORTED;
10716 /****************************************************************
10717 _spoolss_AddPerMachineConnection
10718 ****************************************************************/
10720 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
10721 struct spoolss_AddPerMachineConnection *r)
10723 p->rng_fault_state = true;
10724 return WERR_NOT_SUPPORTED;
10727 /****************************************************************
10728 _spoolss_DeletePerMachineConnection
10729 ****************************************************************/
10731 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
10732 struct spoolss_DeletePerMachineConnection *r)
10734 p->rng_fault_state = true;
10735 return WERR_NOT_SUPPORTED;
10738 /****************************************************************
10739 _spoolss_EnumPerMachineConnections
10740 ****************************************************************/
10742 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
10743 struct spoolss_EnumPerMachineConnections *r)
10745 p->rng_fault_state = true;
10746 return WERR_NOT_SUPPORTED;
10749 /****************************************************************
10750 _spoolss_5a
10751 ****************************************************************/
10753 WERROR _spoolss_5a(struct pipes_struct *p,
10754 struct spoolss_5a *r)
10756 p->rng_fault_state = true;
10757 return WERR_NOT_SUPPORTED;
10760 /****************************************************************
10761 _spoolss_5b
10762 ****************************************************************/
10764 WERROR _spoolss_5b(struct pipes_struct *p,
10765 struct spoolss_5b *r)
10767 p->rng_fault_state = true;
10768 return WERR_NOT_SUPPORTED;
10771 /****************************************************************
10772 _spoolss_5c
10773 ****************************************************************/
10775 WERROR _spoolss_5c(struct pipes_struct *p,
10776 struct spoolss_5c *r)
10778 p->rng_fault_state = true;
10779 return WERR_NOT_SUPPORTED;
10782 /****************************************************************
10783 _spoolss_5d
10784 ****************************************************************/
10786 WERROR _spoolss_5d(struct pipes_struct *p,
10787 struct spoolss_5d *r)
10789 p->rng_fault_state = true;
10790 return WERR_NOT_SUPPORTED;
10793 /****************************************************************
10794 _spoolss_5e
10795 ****************************************************************/
10797 WERROR _spoolss_5e(struct pipes_struct *p,
10798 struct spoolss_5e *r)
10800 p->rng_fault_state = true;
10801 return WERR_NOT_SUPPORTED;
10804 /****************************************************************
10805 _spoolss_5f
10806 ****************************************************************/
10808 WERROR _spoolss_5f(struct pipes_struct *p,
10809 struct spoolss_5f *r)
10811 p->rng_fault_state = true;
10812 return WERR_NOT_SUPPORTED;
10815 /****************************************************************
10816 _spoolss_60
10817 ****************************************************************/
10819 WERROR _spoolss_60(struct pipes_struct *p,
10820 struct spoolss_60 *r)
10822 p->rng_fault_state = true;
10823 return WERR_NOT_SUPPORTED;
10826 /****************************************************************
10827 _spoolss_61
10828 ****************************************************************/
10830 WERROR _spoolss_61(struct pipes_struct *p,
10831 struct spoolss_61 *r)
10833 p->rng_fault_state = true;
10834 return WERR_NOT_SUPPORTED;
10837 /****************************************************************
10838 _spoolss_62
10839 ****************************************************************/
10841 WERROR _spoolss_62(struct pipes_struct *p,
10842 struct spoolss_62 *r)
10844 p->rng_fault_state = true;
10845 return WERR_NOT_SUPPORTED;
10848 /****************************************************************
10849 _spoolss_63
10850 ****************************************************************/
10852 WERROR _spoolss_63(struct pipes_struct *p,
10853 struct spoolss_63 *r)
10855 p->rng_fault_state = true;
10856 return WERR_NOT_SUPPORTED;
10859 /****************************************************************
10860 _spoolss_64
10861 ****************************************************************/
10863 WERROR _spoolss_64(struct pipes_struct *p,
10864 struct spoolss_64 *r)
10866 p->rng_fault_state = true;
10867 return WERR_NOT_SUPPORTED;
10870 /****************************************************************
10871 _spoolss_65
10872 ****************************************************************/
10874 WERROR _spoolss_65(struct pipes_struct *p,
10875 struct spoolss_65 *r)
10877 p->rng_fault_state = true;
10878 return WERR_NOT_SUPPORTED;
10881 /****************************************************************
10882 _spoolss_GetCorePrinterDrivers
10883 ****************************************************************/
10885 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
10886 struct spoolss_GetCorePrinterDrivers *r)
10888 p->rng_fault_state = true;
10889 return WERR_NOT_SUPPORTED;
10892 /****************************************************************
10893 _spoolss_67
10894 ****************************************************************/
10896 WERROR _spoolss_67(struct pipes_struct *p,
10897 struct spoolss_67 *r)
10899 p->rng_fault_state = true;
10900 return WERR_NOT_SUPPORTED;
10903 /****************************************************************
10904 _spoolss_GetPrinterDriverPackagePath
10905 ****************************************************************/
10907 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
10908 struct spoolss_GetPrinterDriverPackagePath *r)
10910 p->rng_fault_state = true;
10911 return WERR_NOT_SUPPORTED;
10914 /****************************************************************
10915 _spoolss_69
10916 ****************************************************************/
10918 WERROR _spoolss_69(struct pipes_struct *p,
10919 struct spoolss_69 *r)
10921 p->rng_fault_state = true;
10922 return WERR_NOT_SUPPORTED;
10925 /****************************************************************
10926 _spoolss_6a
10927 ****************************************************************/
10929 WERROR _spoolss_6a(struct pipes_struct *p,
10930 struct spoolss_6a *r)
10932 p->rng_fault_state = true;
10933 return WERR_NOT_SUPPORTED;
10936 /****************************************************************
10937 _spoolss_6b
10938 ****************************************************************/
10940 WERROR _spoolss_6b(struct pipes_struct *p,
10941 struct spoolss_6b *r)
10943 p->rng_fault_state = true;
10944 return WERR_NOT_SUPPORTED;
10947 /****************************************************************
10948 _spoolss_6c
10949 ****************************************************************/
10951 WERROR _spoolss_6c(struct pipes_struct *p,
10952 struct spoolss_6c *r)
10954 p->rng_fault_state = true;
10955 return WERR_NOT_SUPPORTED;
10958 /****************************************************************
10959 _spoolss_6d
10960 ****************************************************************/
10962 WERROR _spoolss_6d(struct pipes_struct *p,
10963 struct spoolss_6d *r)
10965 p->rng_fault_state = true;
10966 return WERR_NOT_SUPPORTED;