spoolss: make spoolss deal with ndr64 SetForm by using proper container object.
[Samba/gebeck_regimport.git] / source3 / rpc_server / spoolss / srv_spoolss_nt.c
blob6d756bdf3679c32fe38c0b883410635219b63158
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"
58 #include "../libcli/smb/smbXcli_base.h"
60 /* macros stolen from s4 spoolss server */
61 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
62 ((info)?ndr_size_##fn(info, level, 0):0)
64 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
65 ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
67 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
68 ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
70 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
72 #undef DBGC_CLASS
73 #define DBGC_CLASS DBGC_RPC_SRV
75 #ifndef MAX_OPEN_PRINTER_EXS
76 #define MAX_OPEN_PRINTER_EXS 50
77 #endif
79 struct notify_back_channel;
81 /* structure to store the printer handles */
82 /* and a reference to what it's pointing to */
83 /* and the notify info asked about */
84 /* that's the central struct */
85 struct printer_handle {
86 struct printer_handle *prev, *next;
87 bool document_started;
88 bool page_started;
89 uint32 jobid; /* jobid in printing backend */
90 int printer_type;
91 const char *servername;
92 fstring sharename;
93 uint32 type;
94 uint32 access_granted;
95 struct {
96 uint32 flags;
97 uint32 options;
98 fstring localmachine;
99 uint32 printerlocal;
100 struct spoolss_NotifyOption *option;
101 struct policy_handle cli_hnd;
102 struct notify_back_channel *cli_chan;
103 uint32 change;
104 /* are we in a FindNextPrinterChangeNotify() call? */
105 bool fnpcn;
106 struct messaging_context *msg_ctx;
107 } notify;
108 struct {
109 fstring machine;
110 fstring user;
111 } client;
113 /* devmode sent in the OpenPrinter() call */
114 struct spoolss_DeviceMode *devmode;
116 /* TODO cache the printer info2 structure */
117 struct spoolss_PrinterInfo2 *info2;
121 static struct printer_handle *printers_list;
123 struct printer_session_counter {
124 struct printer_session_counter *next;
125 struct printer_session_counter *prev;
127 int snum;
128 uint32_t counter;
131 static struct printer_session_counter *counter_list;
133 struct notify_back_channel {
134 struct notify_back_channel *prev, *next;
136 /* associated client */
137 struct sockaddr_storage client_address;
139 /* print notify back-channel pipe handle*/
140 struct rpc_pipe_client *cli_pipe;
141 uint32_t active_connections;
144 static struct notify_back_channel *back_channels;
146 /* Map generic permissions to printer object specific permissions */
148 const struct standard_mapping printer_std_mapping = {
149 PRINTER_READ,
150 PRINTER_WRITE,
151 PRINTER_EXECUTE,
152 PRINTER_ALL_ACCESS
155 /* Map generic permissions to print server object specific permissions */
157 const struct standard_mapping printserver_std_mapping = {
158 SERVER_READ,
159 SERVER_WRITE,
160 SERVER_EXECUTE,
161 SERVER_ALL_ACCESS
164 /* API table for Xcv Monitor functions */
166 struct xcv_api_table {
167 const char *name;
168 WERROR(*fn) (TALLOC_CTX *mem_ctx, struct security_token *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
171 static void prune_printername_cache(void);
173 /********************************************************************
174 * Canonicalize servername.
175 ********************************************************************/
177 static const char *canon_servername(const char *servername)
179 const char *pservername = servername;
180 while (*pservername == '\\') {
181 pservername++;
183 return pservername;
186 /* translate between internal status numbers and NT status numbers */
187 static int nt_printj_status(int v)
189 switch (v) {
190 case LPQ_QUEUED:
191 return 0;
192 case LPQ_PAUSED:
193 return JOB_STATUS_PAUSED;
194 case LPQ_SPOOLING:
195 return JOB_STATUS_SPOOLING;
196 case LPQ_PRINTING:
197 return JOB_STATUS_PRINTING;
198 case LPQ_ERROR:
199 return JOB_STATUS_ERROR;
200 case LPQ_DELETING:
201 return JOB_STATUS_DELETING;
202 case LPQ_OFFLINE:
203 return JOB_STATUS_OFFLINE;
204 case LPQ_PAPEROUT:
205 return JOB_STATUS_PAPEROUT;
206 case LPQ_PRINTED:
207 return JOB_STATUS_PRINTED;
208 case LPQ_DELETED:
209 return JOB_STATUS_DELETED;
210 case LPQ_BLOCKED:
211 return JOB_STATUS_BLOCKED_DEVQ;
212 case LPQ_USER_INTERVENTION:
213 return JOB_STATUS_USER_INTERVENTION;
215 return 0;
218 static int nt_printq_status(int v)
220 switch (v) {
221 case LPQ_PAUSED:
222 return PRINTER_STATUS_PAUSED;
223 case LPQ_QUEUED:
224 case LPQ_SPOOLING:
225 case LPQ_PRINTING:
226 return 0;
228 return 0;
231 /***************************************************************************
232 Disconnect from the client
233 ****************************************************************************/
235 static void srv_spoolss_replycloseprinter(int snum,
236 struct printer_handle *prn_hnd)
238 WERROR result;
239 NTSTATUS status;
242 * Tell the specific printing tdb we no longer want messages for this printer
243 * by deregistering our PID.
246 if (!print_notify_deregister_pid(snum)) {
247 DEBUG(0, ("Failed to register our pid for printer %s\n",
248 lp_const_servicename(snum)));
251 /* weird if the test succeeds !!! */
252 if (prn_hnd->notify.cli_chan == NULL ||
253 prn_hnd->notify.cli_chan->cli_pipe == NULL ||
254 prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
255 prn_hnd->notify.cli_chan->active_connections == 0) {
256 DEBUG(0, ("Trying to close unexisting backchannel!\n"));
257 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
258 TALLOC_FREE(prn_hnd->notify.cli_chan);
259 return;
262 status = dcerpc_spoolss_ReplyClosePrinter(
263 prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
264 talloc_tos(),
265 &prn_hnd->notify.cli_hnd,
266 &result);
267 if (!NT_STATUS_IS_OK(status)) {
268 DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
269 nt_errstr(status)));
270 result = ntstatus_to_werror(status);
271 } else if (!W_ERROR_IS_OK(result)) {
272 DEBUG(0, ("reply_close_printer failed [%s].\n",
273 win_errstr(result)));
276 /* if it's the last connection, deconnect the IPC$ share */
277 if (prn_hnd->notify.cli_chan->active_connections == 1) {
279 cli_shutdown(rpc_pipe_np_smb_conn(prn_hnd->notify.cli_chan->cli_pipe));
280 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
281 TALLOC_FREE(prn_hnd->notify.cli_chan);
283 if (prn_hnd->notify.msg_ctx != NULL) {
284 messaging_deregister(prn_hnd->notify.msg_ctx,
285 MSG_PRINTER_NOTIFY2, NULL);
289 if (prn_hnd->notify.cli_chan) {
290 prn_hnd->notify.cli_chan->active_connections--;
291 prn_hnd->notify.cli_chan = NULL;
295 /****************************************************************************
296 Functions to free a printer entry datastruct.
297 ****************************************************************************/
299 static int printer_entry_destructor(struct printer_handle *Printer)
301 if (Printer->notify.cli_chan != NULL &&
302 Printer->notify.cli_chan->active_connections > 0) {
303 int snum = -1;
305 switch(Printer->printer_type) {
306 case SPLHND_SERVER:
307 srv_spoolss_replycloseprinter(snum, Printer);
308 break;
310 case SPLHND_PRINTER:
311 snum = print_queue_snum(Printer->sharename);
312 if (snum != -1) {
313 srv_spoolss_replycloseprinter(snum, Printer);
315 break;
316 default:
317 break;
321 Printer->notify.flags=0;
322 Printer->notify.options=0;
323 Printer->notify.localmachine[0]='\0';
324 Printer->notify.printerlocal=0;
325 TALLOC_FREE(Printer->notify.option);
326 TALLOC_FREE(Printer->devmode);
328 /* Remove from the internal list. */
329 DLIST_REMOVE(printers_list, Printer);
330 return 0;
333 /****************************************************************************
334 find printer index by handle
335 ****************************************************************************/
337 static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
338 struct policy_handle *hnd)
340 struct printer_handle *find_printer = NULL;
342 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
343 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
344 return NULL;
347 return find_printer;
350 /****************************************************************************
351 Close printer index by handle.
352 ****************************************************************************/
354 static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
356 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
358 if (!Printer) {
359 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
360 OUR_HANDLE(hnd)));
361 return false;
364 close_policy_hnd(p, hnd);
366 return true;
369 /****************************************************************************
370 Delete a printer given a handle.
371 ****************************************************************************/
373 static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
374 const char *sharename,
375 struct messaging_context *msg_ctx)
377 char *cmd = lp_deleteprinter_cmd(talloc_tos());
378 char *command = NULL;
379 int ret;
380 bool is_print_op = false;
382 /* can't fail if we don't try */
384 if ( !*cmd )
385 return WERR_OK;
387 command = talloc_asprintf(ctx,
388 "%s \"%s\"",
389 cmd, sharename);
390 if (!command) {
391 return WERR_NOMEM;
393 if ( token )
394 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
396 DEBUG(10,("Running [%s]\n", command));
398 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
400 if ( is_print_op )
401 become_root();
403 if ( (ret = smbrun(command, NULL)) == 0 ) {
404 /* Tell everyone we updated smb.conf. */
405 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
408 if ( is_print_op )
409 unbecome_root();
411 /********** END SePrintOperatorPrivlege BLOCK **********/
413 DEBUGADD(10,("returned [%d]\n", ret));
415 TALLOC_FREE(command);
417 if (ret != 0)
418 return WERR_BADFID; /* What to return here? */
420 return WERR_OK;
423 /****************************************************************************
424 Delete a printer given a handle.
425 ****************************************************************************/
427 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
429 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
430 WERROR result;
432 if (!Printer) {
433 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
434 OUR_HANDLE(hnd)));
435 return WERR_BADFID;
439 * It turns out that Windows allows delete printer on a handle
440 * opened by an admin user, then used on a pipe handle created
441 * by an anonymous user..... but they're working on security.... riiight !
442 * JRA.
445 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
446 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
447 return WERR_ACCESS_DENIED;
450 /* this does not need a become root since the access check has been
451 done on the handle already */
453 result = winreg_delete_printer_key_internal(p->mem_ctx,
454 get_session_info_system(),
455 p->msg_ctx,
456 Printer->sharename,
457 "");
458 if (!W_ERROR_IS_OK(result)) {
459 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
460 return WERR_BADFID;
463 result = delete_printer_hook(p->mem_ctx, p->session_info->security_token,
464 Printer->sharename, p->msg_ctx);
465 if (!W_ERROR_IS_OK(result)) {
466 return result;
468 prune_printername_cache();
469 return WERR_OK;
472 /****************************************************************************
473 Return the snum of a printer corresponding to an handle.
474 ****************************************************************************/
476 static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
477 int *number, struct share_params **params)
479 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
481 if (!Printer) {
482 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
483 OUR_HANDLE(hnd)));
484 return false;
487 switch (Printer->printer_type) {
488 case SPLHND_PRINTER:
489 DEBUG(4,("short name:%s\n", Printer->sharename));
490 *number = print_queue_snum(Printer->sharename);
491 return (*number != -1);
492 case SPLHND_SERVER:
493 return false;
494 default:
495 return false;
499 /****************************************************************************
500 Set printer handle type.
501 Check if it's \\server or \\server\printer
502 ****************************************************************************/
504 static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
506 DEBUG(3,("Setting printer type=%s\n", handlename));
508 /* it's a print server */
509 if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
510 DEBUGADD(4,("Printer is a print server\n"));
511 Printer->printer_type = SPLHND_SERVER;
513 /* it's a printer (set_printer_hnd_name() will handle port monitors */
514 else {
515 DEBUGADD(4,("Printer is a printer\n"));
516 Printer->printer_type = SPLHND_PRINTER;
519 return true;
522 static void prune_printername_cache_fn(const char *key, const char *value,
523 time_t timeout, void *private_data)
525 gencache_del(key);
528 static void prune_printername_cache(void)
530 gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
533 /****************************************************************************
534 Set printer handle name.. Accept names like \\server, \\server\printer,
535 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
536 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
537 XcvDataPort() interface.
538 ****************************************************************************/
540 static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
541 const struct auth_session_info *session_info,
542 struct messaging_context *msg_ctx,
543 struct printer_handle *Printer,
544 const char *handlename)
546 int snum;
547 int n_services=lp_numservices();
548 char *aprinter;
549 const char *printername;
550 const char *servername = NULL;
551 fstring sname;
552 bool found = false;
553 struct spoolss_PrinterInfo2 *info2 = NULL;
554 WERROR result;
555 char *p;
558 * Hopefully nobody names his printers like this. Maybe \ or ,
559 * are illegal in printer names even?
561 const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
562 char *cache_key;
563 char *tmp;
565 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
566 (unsigned long)strlen(handlename)));
568 aprinter = discard_const_p(char, handlename);
569 if ( *handlename == '\\' ) {
570 servername = canon_servername(handlename);
571 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
572 *aprinter = '\0';
573 aprinter++;
575 if (!is_myname_or_ipaddr(servername)) {
576 return WERR_INVALID_PRINTER_NAME;
578 Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
579 if (Printer->servername == NULL) {
580 return WERR_NOMEM;
584 if (Printer->printer_type == SPLHND_SERVER) {
585 return WERR_OK;
588 if (Printer->printer_type != SPLHND_PRINTER) {
589 return WERR_INVALID_HANDLE;
592 DEBUGADD(5, ("searching for [%s]\n", aprinter));
594 p = strchr(aprinter, ',');
595 if (p != NULL) {
596 char *p2 = p;
597 p++;
598 if (*p == ' ') {
599 p++;
601 if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
602 *p2 = '\0';
603 } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
604 *p2 = '\0';
608 if (p) {
609 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
612 /* check for the Port Monitor Interface */
613 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
614 Printer->printer_type = SPLHND_PORTMON_TCP;
615 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
616 found = true;
618 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
619 Printer->printer_type = SPLHND_PORTMON_LOCAL;
620 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
621 found = true;
625 * With hundreds of printers, the "for" loop iterating all
626 * shares can be quite expensive, as it is done on every
627 * OpenPrinter. The loop maps "aprinter" to "sname", the
628 * result of which we cache in gencache.
631 cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s",
632 aprinter);
633 if ((cache_key != NULL) && gencache_get(cache_key, &tmp, NULL)) {
635 found = (strcmp(tmp, printer_not_found) != 0);
636 if (!found) {
637 DEBUG(4, ("Printer %s not found\n", aprinter));
638 SAFE_FREE(tmp);
639 return WERR_INVALID_PRINTER_NAME;
641 fstrcpy(sname, tmp);
642 SAFE_FREE(tmp);
645 /* Search all sharenames first as this is easier than pulling
646 the printer_info_2 off of disk. Don't use find_service() since
647 that calls out to map_username() */
649 /* do another loop to look for printernames */
650 for (snum = 0; !found && snum < n_services; snum++) {
651 const char *printer = lp_const_servicename(snum);
653 /* no point going on if this is not a printer */
654 if (!(lp_snum_ok(snum) && lp_print_ok(snum))) {
655 continue;
658 /* ignore [printers] share */
659 if (strequal(printer, "printers")) {
660 continue;
663 fstrcpy(sname, printer);
664 if (strequal(aprinter, printer)) {
665 found = true;
666 break;
669 /* no point looking up the printer object if
670 we aren't allowing printername != sharename */
671 if (lp_force_printername(snum)) {
672 continue;
675 result = winreg_get_printer_internal(mem_ctx,
676 session_info,
677 msg_ctx,
678 sname,
679 &info2);
680 if ( !W_ERROR_IS_OK(result) ) {
681 DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
682 sname, win_errstr(result)));
683 continue;
686 printername = strrchr(info2->printername, '\\');
687 if (printername == NULL) {
688 printername = info2->printername;
689 } else {
690 printername++;
693 if (strequal(printername, aprinter)) {
694 found = true;
695 break;
698 DEBUGADD(10, ("printername: %s\n", printername));
700 TALLOC_FREE(info2);
703 if ( !found ) {
704 if (cache_key != NULL) {
705 gencache_set(cache_key, printer_not_found,
706 time(NULL)+300);
707 TALLOC_FREE(cache_key);
709 DEBUGADD(4,("Printer not found\n"));
710 return WERR_INVALID_PRINTER_NAME;
713 if (cache_key != NULL) {
714 gencache_set(cache_key, sname, time(NULL)+300);
715 TALLOC_FREE(cache_key);
718 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
720 strlcpy(Printer->sharename, sname, sizeof(Printer->sharename));
722 return WERR_OK;
725 /****************************************************************************
726 Find first available printer slot. creates a printer handle for you.
727 ****************************************************************************/
729 static WERROR open_printer_hnd(struct pipes_struct *p,
730 struct policy_handle *hnd,
731 const char *name,
732 uint32_t access_granted)
734 struct printer_handle *new_printer;
735 WERROR result;
737 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
739 new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
740 if (new_printer == NULL) {
741 return WERR_NOMEM;
743 talloc_set_destructor(new_printer, printer_entry_destructor);
745 /* This also steals the printer_handle on the policy_handle */
746 if (!create_policy_hnd(p, hnd, new_printer)) {
747 TALLOC_FREE(new_printer);
748 return WERR_INVALID_HANDLE;
751 /* Add to the internal list. */
752 DLIST_ADD(printers_list, new_printer);
754 new_printer->notify.option=NULL;
756 if (!set_printer_hnd_printertype(new_printer, name)) {
757 close_printer_handle(p, hnd);
758 return WERR_INVALID_HANDLE;
761 result = set_printer_hnd_name(p->mem_ctx,
762 get_session_info_system(),
763 p->msg_ctx,
764 new_printer, name);
765 if (!W_ERROR_IS_OK(result)) {
766 close_printer_handle(p, hnd);
767 return result;
770 new_printer->access_granted = access_granted;
772 DEBUG(5, ("%d printer handles active\n",
773 (int)num_pipe_handles(p)));
775 return WERR_OK;
778 /***************************************************************************
779 check to see if the client motify handle is monitoring the notification
780 given by (notify_type, notify_field).
781 **************************************************************************/
783 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
784 uint16_t notify_field)
786 return true;
789 static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
790 uint16_t notify_field)
792 struct spoolss_NotifyOption *option = p->notify.option;
793 uint32_t i, j;
796 * Flags should always be zero when the change notify
797 * is registered by the client's spooler. A user Win32 app
798 * might use the flags though instead of the NOTIFY_OPTION_INFO
799 * --jerry
802 if (!option) {
803 return false;
806 if (p->notify.flags)
807 return is_monitoring_event_flags(
808 p->notify.flags, notify_type, notify_field);
810 for (i = 0; i < option->count; i++) {
812 /* Check match for notify_type */
814 if (option->types[i].type != notify_type)
815 continue;
817 /* Check match for field */
819 for (j = 0; j < option->types[i].count; j++) {
820 if (option->types[i].fields[j].field == notify_field) {
821 return true;
826 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
827 p->servername, p->sharename, notify_type, notify_field));
829 return false;
832 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
833 _data->data.integer[0] = _integer; \
834 _data->data.integer[1] = 0;
837 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
838 _data->data.string.string = talloc_strdup(mem_ctx, _p); \
839 if (!_data->data.string.string) {\
840 _data->data.string.size = 0; \
842 _data->data.string.size = strlen_m_term(_p) * 2;
844 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
845 _data->data.devmode.devmode = _devmode;
847 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
848 _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
849 if (!_data->data.sd.sd) { \
850 _data->data.sd.sd_size = 0; \
852 _data->data.sd.sd_size = \
853 ndr_size_security_descriptor(_data->data.sd.sd, 0);
855 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
856 struct tm *t,
857 const char **pp,
858 uint32_t *plen)
860 struct spoolss_Time st;
861 uint32_t len = 16;
862 char *p;
864 if (!init_systemtime(&st, t)) {
865 return;
868 p = talloc_array(mem_ctx, char, len);
869 if (!p) {
870 return;
874 * Systemtime must be linearized as a set of UINT16's.
875 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
878 SSVAL(p, 0, st.year);
879 SSVAL(p, 2, st.month);
880 SSVAL(p, 4, st.day_of_week);
881 SSVAL(p, 6, st.day);
882 SSVAL(p, 8, st.hour);
883 SSVAL(p, 10, st.minute);
884 SSVAL(p, 12, st.second);
885 SSVAL(p, 14, st.millisecond);
887 *pp = p;
888 *plen = len;
891 /* Convert a notification message to a struct spoolss_Notify */
893 static void notify_one_value(struct spoolss_notify_msg *msg,
894 struct spoolss_Notify *data,
895 TALLOC_CTX *mem_ctx)
897 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
900 static void notify_string(struct spoolss_notify_msg *msg,
901 struct spoolss_Notify *data,
902 TALLOC_CTX *mem_ctx)
904 /* The length of the message includes the trailing \0 */
906 data->data.string.size = msg->len * 2;
907 data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
908 if (!data->data.string.string) {
909 data->data.string.size = 0;
910 return;
914 static void notify_system_time(struct spoolss_notify_msg *msg,
915 struct spoolss_Notify *data,
916 TALLOC_CTX *mem_ctx)
918 data->data.string.string = NULL;
919 data->data.string.size = 0;
921 if (msg->len != sizeof(time_t)) {
922 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
923 msg->len));
924 return;
927 init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
928 &data->data.string.string,
929 &data->data.string.size);
932 struct notify2_message_table {
933 const char *name;
934 void (*fn)(struct spoolss_notify_msg *msg,
935 struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
938 static struct notify2_message_table printer_notify_table[] = {
939 /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
940 /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
941 /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
942 /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
943 /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
944 /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
945 /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
946 /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
947 /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
948 /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
949 /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
950 /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
951 /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
952 /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
953 /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
954 /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
955 /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
956 /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
957 /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
960 static struct notify2_message_table job_notify_table[] = {
961 /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
962 /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
963 /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
964 /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
965 /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
966 /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
967 /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
968 /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
969 /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
970 /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
971 /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
972 /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
973 /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
974 /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
975 /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
976 /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
977 /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
978 /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
979 /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
980 /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
981 /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
982 /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
983 /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
984 /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
988 /***********************************************************************
989 Allocate talloc context for container object
990 **********************************************************************/
992 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
994 if ( !ctr )
995 return;
997 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
999 return;
1002 /***********************************************************************
1003 release all allocated memory and zero out structure
1004 **********************************************************************/
1006 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1008 if ( !ctr )
1009 return;
1011 if ( ctr->ctx )
1012 talloc_destroy(ctr->ctx);
1014 ZERO_STRUCTP(ctr);
1016 return;
1019 /***********************************************************************
1020 **********************************************************************/
1022 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1024 if ( !ctr )
1025 return NULL;
1027 return ctr->ctx;
1030 /***********************************************************************
1031 **********************************************************************/
1033 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1035 if ( !ctr || !ctr->msg_groups )
1036 return NULL;
1038 if ( idx >= ctr->num_groups )
1039 return NULL;
1041 return &ctr->msg_groups[idx];
1045 /***********************************************************************
1046 How many groups of change messages do we have ?
1047 **********************************************************************/
1049 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1051 if ( !ctr )
1052 return 0;
1054 return ctr->num_groups;
1057 /***********************************************************************
1058 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1059 **********************************************************************/
1061 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1063 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
1064 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
1065 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
1066 int i, new_slot;
1068 if ( !ctr || !msg )
1069 return 0;
1071 /* loop over all groups looking for a matching printer name */
1073 for ( i=0; i<ctr->num_groups; i++ ) {
1074 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1075 break;
1078 /* add a new group? */
1080 if ( i == ctr->num_groups ) {
1081 ctr->num_groups++;
1083 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1084 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1085 return 0;
1087 ctr->msg_groups = groups;
1089 /* clear the new entry and set the printer name */
1091 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1092 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1095 /* add the change messages; 'i' is the correct index now regardless */
1097 msg_grp = &ctr->msg_groups[i];
1099 msg_grp->num_msgs++;
1101 if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1102 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1103 return 0;
1105 msg_grp->msgs = msg_list;
1107 new_slot = msg_grp->num_msgs-1;
1108 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1110 /* need to allocate own copy of data */
1112 if ( msg->len != 0 )
1113 msg_grp->msgs[new_slot].notify.data = (char *)
1114 talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
1116 return ctr->num_groups;
1119 static void construct_info_data(struct spoolss_Notify *info_data,
1120 enum spoolss_NotifyType type,
1121 uint16_t field, int id);
1123 /***********************************************************************
1124 Send a change notication message on all handles which have a call
1125 back registered
1126 **********************************************************************/
1128 static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1129 struct printer_handle *prn_hnd,
1130 SPOOLSS_NOTIFY_MSG *messages,
1131 uint32_t num_msgs,
1132 struct spoolss_Notify **_notifies,
1133 int *_count)
1135 struct spoolss_Notify *notifies;
1136 SPOOLSS_NOTIFY_MSG *msg;
1137 int count = 0;
1138 uint32_t id;
1139 int i;
1141 notifies = talloc_zero_array(mem_ctx,
1142 struct spoolss_Notify, num_msgs);
1143 if (!notifies) {
1144 return ENOMEM;
1147 for (i = 0; i < num_msgs; i++) {
1149 msg = &messages[i];
1151 /* Are we monitoring this event? */
1153 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1154 continue;
1157 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1158 "for printer [%s]\n",
1159 msg->type, msg->field, prn_hnd->sharename));
1162 * if the is a printer notification handle and not a job
1163 * notification type, then set the id to 0.
1164 * Otherwise just use what was specified in the message.
1166 * When registering change notification on a print server
1167 * handle we always need to send back the id (snum) matching
1168 * the printer for which the change took place.
1169 * For change notify registered on a printer handle,
1170 * this does not matter and the id should be 0.
1172 * --jerry
1175 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1176 (prn_hnd->printer_type == SPLHND_PRINTER)) {
1177 id = 0;
1178 } else {
1179 id = msg->id;
1182 /* Convert unix jobid to smb jobid */
1184 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1185 id = sysjob_to_jobid(msg->id);
1187 if (id == -1) {
1188 DEBUG(3, ("no such unix jobid %d\n",
1189 msg->id));
1190 continue;
1194 construct_info_data(&notifies[count],
1195 msg->type, msg->field, id);
1197 switch(msg->type) {
1198 case PRINTER_NOTIFY_TYPE:
1199 if (printer_notify_table[msg->field].fn) {
1200 printer_notify_table[msg->field].fn(msg,
1201 &notifies[count], mem_ctx);
1203 break;
1205 case JOB_NOTIFY_TYPE:
1206 if (job_notify_table[msg->field].fn) {
1207 job_notify_table[msg->field].fn(msg,
1208 &notifies[count], mem_ctx);
1210 break;
1212 default:
1213 DEBUG(5, ("Unknown notification type %d\n",
1214 msg->type));
1215 continue;
1218 count++;
1221 *_notifies = notifies;
1222 *_count = count;
1224 return 0;
1227 static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1228 struct printer_handle *prn_hnd,
1229 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1231 struct spoolss_Notify *notifies;
1232 int count = 0;
1233 union spoolss_ReplyPrinterInfo info;
1234 struct spoolss_NotifyInfo info0;
1235 uint32_t reply_result;
1236 NTSTATUS status;
1237 WERROR werr;
1238 int ret;
1240 /* Is there notification on this handle? */
1241 if (prn_hnd->notify.cli_chan == NULL ||
1242 prn_hnd->notify.cli_chan->cli_pipe == NULL ||
1243 prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
1244 prn_hnd->notify.cli_chan->active_connections == 0) {
1245 return 0;
1248 DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1249 prn_hnd->servername, prn_hnd->sharename));
1251 /* For this printer? Print servers always receive notifications. */
1252 if ((prn_hnd->printer_type == SPLHND_PRINTER) &&
1253 (!strequal(msg_group->printername, prn_hnd->sharename))) {
1254 return 0;
1257 DEBUG(10,("Our printer\n"));
1259 /* build the array of change notifications */
1260 ret = build_notify2_messages(mem_ctx, prn_hnd,
1261 msg_group->msgs,
1262 msg_group->num_msgs,
1263 &notifies, &count);
1264 if (ret) {
1265 return ret;
1268 info0.version = 0x2;
1269 info0.flags = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1270 info0.count = count;
1271 info0.notifies = notifies;
1273 info.info0 = &info0;
1275 status = dcerpc_spoolss_RouterReplyPrinterEx(
1276 prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
1277 mem_ctx,
1278 &prn_hnd->notify.cli_hnd,
1279 prn_hnd->notify.change, /* color */
1280 prn_hnd->notify.flags,
1281 &reply_result,
1282 0, /* reply_type, must be 0 */
1283 info, &werr);
1284 if (!NT_STATUS_IS_OK(status)) {
1285 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1286 "failed: %s\n",
1287 prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1288 nt_errstr(status)));
1289 werr = ntstatus_to_werror(status);
1290 } else if (!W_ERROR_IS_OK(werr)) {
1291 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1292 "failed: %s\n",
1293 prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1294 win_errstr(werr)));
1296 switch (reply_result) {
1297 case 0:
1298 break;
1299 case PRINTER_NOTIFY_INFO_DISCARDED:
1300 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1301 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1302 break;
1303 default:
1304 break;
1307 return 0;
1310 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1312 struct printer_handle *p;
1313 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
1314 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1315 int ret;
1317 if ( !msg_group ) {
1318 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1319 return;
1322 if (!msg_group->msgs) {
1323 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1324 return;
1327 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1329 /* loop over all printers */
1331 for (p = printers_list; p; p = p->next) {
1332 ret = send_notify2_printer(mem_ctx, p, msg_group);
1333 if (ret) {
1334 goto done;
1338 done:
1339 DEBUG(8,("send_notify2_changes: Exit...\n"));
1340 return;
1343 /***********************************************************************
1344 **********************************************************************/
1346 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1349 uint32_t tv_sec, tv_usec;
1350 size_t offset = 0;
1352 /* Unpack message */
1354 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1355 msg->printer);
1357 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1358 &tv_sec, &tv_usec,
1359 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1361 if (msg->len == 0)
1362 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1363 &msg->notify.value[0], &msg->notify.value[1]);
1364 else
1365 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1366 &msg->len, &msg->notify.data);
1368 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1369 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1371 tv->tv_sec = tv_sec;
1372 tv->tv_usec = tv_usec;
1374 if (msg->len == 0)
1375 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1376 msg->notify.value[1]));
1377 else
1378 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1380 return true;
1383 /********************************************************************
1384 Receive a notify2 message list
1385 ********************************************************************/
1387 static void receive_notify2_message_list(struct messaging_context *msg,
1388 void *private_data,
1389 uint32_t msg_type,
1390 struct server_id server_id,
1391 DATA_BLOB *data)
1393 size_t msg_count, i;
1394 char *buf = (char *)data->data;
1395 char *msg_ptr;
1396 size_t msg_len;
1397 SPOOLSS_NOTIFY_MSG notify;
1398 SPOOLSS_NOTIFY_MSG_CTR messages;
1399 int num_groups;
1401 if (data->length < 4) {
1402 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1403 return;
1406 msg_count = IVAL(buf, 0);
1407 msg_ptr = buf + 4;
1409 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1411 if (msg_count == 0) {
1412 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1413 return;
1416 /* initialize the container */
1418 ZERO_STRUCT( messages );
1419 notify_msg_ctr_init( &messages );
1422 * build message groups for each printer identified
1423 * in a change_notify msg. Remember that a PCN message
1424 * includes the handle returned for the srv_spoolss_replyopenprinter()
1425 * call. Therefore messages are grouped according to printer handle.
1428 for ( i=0; i<msg_count; i++ ) {
1429 struct timeval msg_tv;
1431 if (msg_ptr + 4 - buf > data->length) {
1432 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1433 return;
1436 msg_len = IVAL(msg_ptr,0);
1437 msg_ptr += 4;
1439 if (msg_ptr + msg_len - buf > data->length) {
1440 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1441 return;
1444 /* unpack messages */
1446 ZERO_STRUCT( notify );
1447 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1448 msg_ptr += msg_len;
1450 /* add to correct list in container */
1452 notify_msg_ctr_addmsg( &messages, &notify );
1454 /* free memory that might have been allocated by notify2_unpack_msg() */
1456 if ( notify.len != 0 )
1457 SAFE_FREE( notify.notify.data );
1460 /* process each group of messages */
1462 num_groups = notify_msg_ctr_numgroups( &messages );
1463 for ( i=0; i<num_groups; i++ )
1464 send_notify2_changes( &messages, i );
1467 /* cleanup */
1469 DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1470 (uint32_t)msg_count ));
1472 notify_msg_ctr_destroy( &messages );
1474 return;
1477 /********************************************************************
1478 Send a message to ourself about new driver being installed
1479 so we can upgrade the information for each printer bound to this
1480 driver
1481 ********************************************************************/
1483 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1484 struct messaging_context *msg_ctx)
1486 int len = strlen(drivername);
1488 if (!len)
1489 return false;
1491 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1492 drivername));
1494 messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1495 MSG_PRINTER_DRVUPGRADE,
1496 (const uint8_t *)drivername, len+1);
1498 return true;
1501 void srv_spoolss_cleanup(void)
1503 struct printer_session_counter *session_counter;
1505 for (session_counter = counter_list;
1506 session_counter != NULL;
1507 session_counter = counter_list) {
1508 DLIST_REMOVE(counter_list, session_counter);
1509 TALLOC_FREE(session_counter);
1513 /**********************************************************************
1514 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1515 over all printers, upgrading ones as necessary
1516 **********************************************************************/
1518 void do_drv_upgrade_printer(struct messaging_context *msg,
1519 void *private_data,
1520 uint32_t msg_type,
1521 struct server_id server_id,
1522 DATA_BLOB *data)
1524 TALLOC_CTX *tmp_ctx;
1525 const struct auth_session_info *session_info = get_session_info_system();
1526 struct spoolss_PrinterInfo2 *pinfo2;
1527 WERROR result;
1528 const char *drivername;
1529 int snum;
1530 int n_services = lp_numservices();
1531 struct dcerpc_binding_handle *b = NULL;
1533 tmp_ctx = talloc_new(NULL);
1534 if (!tmp_ctx) return;
1536 drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1537 if (!drivername) {
1538 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1539 goto done;
1542 DEBUG(10, ("do_drv_upgrade_printer: "
1543 "Got message for new driver [%s]\n", drivername));
1545 /* Iterate the printer list */
1547 for (snum = 0; snum < n_services; snum++) {
1548 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1549 continue;
1552 /* ignore [printers] share */
1553 if (strequal(lp_const_servicename(snum), "printers")) {
1554 continue;
1557 if (b == NULL) {
1558 result = winreg_printer_binding_handle(tmp_ctx,
1559 session_info,
1560 msg,
1561 &b);
1562 if (!W_ERROR_IS_OK(result)) {
1563 break;
1567 result = winreg_get_printer(tmp_ctx, b,
1568 lp_const_servicename(snum),
1569 &pinfo2);
1571 if (!W_ERROR_IS_OK(result)) {
1572 continue;
1575 if (!pinfo2->drivername) {
1576 continue;
1579 if (strcmp(drivername, pinfo2->drivername) != 0) {
1580 continue;
1583 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1585 /* all we care about currently is the change_id */
1586 result = winreg_printer_update_changeid(tmp_ctx, b,
1587 pinfo2->printername);
1589 if (!W_ERROR_IS_OK(result)) {
1590 DEBUG(3, ("do_drv_upgrade_printer: "
1591 "Failed to update changeid [%s]\n",
1592 win_errstr(result)));
1596 /* all done */
1597 done:
1598 talloc_free(tmp_ctx);
1601 /********************************************************************
1602 Update the cache for all printq's with a registered client
1603 connection
1604 ********************************************************************/
1606 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1608 struct printer_handle *printer = printers_list;
1609 int snum;
1611 /* loop through all printers and update the cache where
1612 a client is connected */
1613 while (printer) {
1614 if ((printer->printer_type == SPLHND_PRINTER) &&
1615 ((printer->notify.cli_chan != NULL) &&
1616 (printer->notify.cli_chan->active_connections > 0))) {
1617 snum = print_queue_snum(printer->sharename);
1618 print_queue_status(msg_ctx, snum, NULL, NULL);
1621 printer = printer->next;
1624 return;
1627 /****************************************************************
1628 _spoolss_OpenPrinter
1629 ****************************************************************/
1631 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1632 struct spoolss_OpenPrinter *r)
1634 struct spoolss_OpenPrinterEx e;
1635 struct spoolss_UserLevel1 level1;
1636 WERROR werr;
1638 ZERO_STRUCT(level1);
1640 e.in.printername = r->in.printername;
1641 e.in.datatype = r->in.datatype;
1642 e.in.devmode_ctr = r->in.devmode_ctr;
1643 e.in.access_mask = r->in.access_mask;
1644 e.in.userlevel_ctr.level = 1;
1645 e.in.userlevel_ctr.user_info.level1 = &level1;
1647 e.out.handle = r->out.handle;
1649 werr = _spoolss_OpenPrinterEx(p, &e);
1651 if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1652 /* OpenPrinterEx returns this for a bad
1653 * printer name. We must return WERR_INVALID_PRINTER_NAME
1654 * instead.
1656 werr = WERR_INVALID_PRINTER_NAME;
1659 return werr;
1662 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1663 struct spoolss_DeviceMode *orig,
1664 struct spoolss_DeviceMode **dest)
1666 struct spoolss_DeviceMode *dm;
1668 dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1669 if (!dm) {
1670 return WERR_NOMEM;
1673 /* copy all values, then duplicate strings and structs */
1674 *dm = *orig;
1676 dm->devicename = talloc_strdup(dm, orig->devicename);
1677 if (!dm->devicename) {
1678 return WERR_NOMEM;
1680 dm->formname = talloc_strdup(dm, orig->formname);
1681 if (!dm->formname) {
1682 return WERR_NOMEM;
1684 if (orig->driverextra_data.data) {
1685 dm->driverextra_data.data =
1686 (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1687 orig->driverextra_data.length);
1688 if (!dm->driverextra_data.data) {
1689 return WERR_NOMEM;
1693 *dest = dm;
1694 return WERR_OK;
1697 /****************************************************************
1698 _spoolss_OpenPrinterEx
1699 ****************************************************************/
1701 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1702 struct spoolss_OpenPrinterEx *r)
1704 int snum;
1705 char *raddr;
1706 char *rhost;
1707 struct printer_handle *Printer=NULL;
1708 WERROR result;
1709 int rc;
1711 if (!r->in.printername) {
1712 return WERR_INVALID_PARAM;
1715 if (!*r->in.printername) {
1716 return WERR_INVALID_PARAM;
1719 if (r->in.userlevel_ctr.level > 3) {
1720 return WERR_INVALID_PARAM;
1722 if ((r->in.userlevel_ctr.level == 1 && !r->in.userlevel_ctr.user_info.level1) ||
1723 (r->in.userlevel_ctr.level == 2 && !r->in.userlevel_ctr.user_info.level2) ||
1724 (r->in.userlevel_ctr.level == 3 && !r->in.userlevel_ctr.user_info.level3)) {
1725 return WERR_INVALID_PARAM;
1728 /* some sanity check because you can open a printer or a print server */
1729 /* aka: \\server\printer or \\server */
1731 DEBUGADD(3,("checking name: %s\n", r->in.printername));
1733 result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1734 if (!W_ERROR_IS_OK(result)) {
1735 DEBUG(0,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1736 "for printer %s\n", r->in.printername));
1737 ZERO_STRUCTP(r->out.handle);
1738 return result;
1741 Printer = find_printer_index_by_hnd(p, r->out.handle);
1742 if ( !Printer ) {
1743 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1744 "handle we created for printer %s\n", r->in.printername));
1745 close_printer_handle(p, r->out.handle);
1746 ZERO_STRUCTP(r->out.handle);
1747 return WERR_INVALID_PARAM;
1751 * First case: the user is opening the print server:
1753 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1754 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1756 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1757 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1758 * or if the user is listed in the smb.conf printer admin parameter.
1760 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1761 * client view printer folder, but does not show the MSAPW.
1763 * Note: this test needs code to check access rights here too. Jeremy
1764 * could you look at this?
1766 * Second case: the user is opening a printer:
1767 * NT doesn't let us connect to a printer if the connecting user
1768 * doesn't have print permission.
1770 * Third case: user is opening a Port Monitor
1771 * access checks same as opening a handle to the print server.
1774 switch (Printer->printer_type )
1776 case SPLHND_SERVER:
1777 case SPLHND_PORTMON_TCP:
1778 case SPLHND_PORTMON_LOCAL:
1779 /* Printserver handles use global struct... */
1781 snum = -1;
1783 /* Map standard access rights to object specific access rights */
1785 se_map_standard(&r->in.access_mask,
1786 &printserver_std_mapping);
1788 /* Deny any object specific bits that don't apply to print
1789 servers (i.e printer and job specific bits) */
1791 r->in.access_mask &= SEC_MASK_SPECIFIC;
1793 if (r->in.access_mask &
1794 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1795 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1796 close_printer_handle(p, r->out.handle);
1797 ZERO_STRUCTP(r->out.handle);
1798 return WERR_ACCESS_DENIED;
1801 /* Allow admin access */
1803 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1805 if (!lp_ms_add_printer_wizard()) {
1806 close_printer_handle(p, r->out.handle);
1807 ZERO_STRUCTP(r->out.handle);
1808 return WERR_ACCESS_DENIED;
1811 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1812 and not a printer admin, then fail */
1814 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
1815 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
1816 !nt_token_check_sid(&global_sid_Builtin_Print_Operators,
1817 p->session_info->security_token)) {
1818 close_printer_handle(p, r->out.handle);
1819 ZERO_STRUCTP(r->out.handle);
1820 DEBUG(3,("access DENIED as user is not root, "
1821 "has no printoperator privilege, "
1822 "not a member of the printoperator builtin group and "
1823 "is not in printer admin list"));
1824 return WERR_ACCESS_DENIED;
1827 r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1829 else
1831 r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1834 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1835 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1837 /* We fall through to return WERR_OK */
1838 break;
1840 case SPLHND_PRINTER:
1841 /* NT doesn't let us connect to a printer if the connecting user
1842 doesn't have print permission. */
1844 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1845 close_printer_handle(p, r->out.handle);
1846 ZERO_STRUCTP(r->out.handle);
1847 return WERR_BADFID;
1850 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1851 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1854 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1856 /* map an empty access mask to the minimum access mask */
1857 if (r->in.access_mask == 0x0)
1858 r->in.access_mask = PRINTER_ACCESS_USE;
1861 * If we are not serving the printer driver for this printer,
1862 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1863 * will keep NT clients happy --jerry
1866 if (lp_use_client_driver(snum)
1867 && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1869 r->in.access_mask = PRINTER_ACCESS_USE;
1872 /* check smb.conf parameters and the the sec_desc */
1873 raddr = tsocket_address_inet_addr_string(p->remote_address,
1874 p->mem_ctx);
1875 if (raddr == NULL) {
1876 return WERR_NOMEM;
1879 rc = get_remote_hostname(p->remote_address,
1880 &rhost,
1881 p->mem_ctx);
1882 if (rc < 0) {
1883 return WERR_NOMEM;
1885 if (strequal(rhost, "UNKNOWN")) {
1886 rhost = raddr;
1889 if (!allow_access(lp_hostsdeny(snum), lp_hostsallow(snum),
1890 rhost, raddr)) {
1891 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1892 ZERO_STRUCTP(r->out.handle);
1893 return WERR_ACCESS_DENIED;
1896 if (!user_ok_token(uidtoname(p->session_info->unix_token->uid), NULL,
1897 p->session_info->security_token, snum) ||
1898 !print_access_check(p->session_info,
1899 p->msg_ctx,
1900 snum,
1901 r->in.access_mask)) {
1902 DEBUG(3, ("access DENIED for printer open\n"));
1903 close_printer_handle(p, r->out.handle);
1904 ZERO_STRUCTP(r->out.handle);
1905 return WERR_ACCESS_DENIED;
1908 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1909 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1910 close_printer_handle(p, r->out.handle);
1911 ZERO_STRUCTP(r->out.handle);
1912 return WERR_ACCESS_DENIED;
1915 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1916 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1917 else
1918 r->in.access_mask = PRINTER_ACCESS_USE;
1920 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1921 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1923 winreg_create_printer_internal(p->mem_ctx,
1924 get_session_info_system(),
1925 p->msg_ctx,
1926 lp_const_servicename(snum));
1928 break;
1930 default:
1931 /* sanity check to prevent programmer error */
1932 ZERO_STRUCTP(r->out.handle);
1933 return WERR_BADFID;
1936 Printer->access_granted = r->in.access_mask;
1939 * If the client sent a devmode in the OpenPrinter() call, then
1940 * save it here in case we get a job submission on this handle
1943 if ((Printer->printer_type != SPLHND_SERVER)
1944 && (r->in.devmode_ctr.devmode != NULL)) {
1945 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1946 &Printer->devmode);
1949 return WERR_OK;
1952 /****************************************************************
1953 _spoolss_ClosePrinter
1954 ****************************************************************/
1956 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1957 struct spoolss_ClosePrinter *r)
1959 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1961 if (Printer && Printer->document_started) {
1962 struct spoolss_EndDocPrinter e;
1964 e.in.handle = r->in.handle;
1966 _spoolss_EndDocPrinter(p, &e);
1969 if (!close_printer_handle(p, r->in.handle))
1970 return WERR_BADFID;
1972 /* clear the returned printer handle. Observed behavior
1973 from Win2k server. Don't think this really matters.
1974 Previous code just copied the value of the closed
1975 handle. --jerry */
1977 ZERO_STRUCTP(r->out.handle);
1979 return WERR_OK;
1982 /****************************************************************
1983 _spoolss_DeletePrinter
1984 ****************************************************************/
1986 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
1987 struct spoolss_DeletePrinter *r)
1989 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1990 WERROR result;
1991 int snum;
1993 if (Printer && Printer->document_started) {
1994 struct spoolss_EndDocPrinter e;
1996 e.in.handle = r->in.handle;
1998 _spoolss_EndDocPrinter(p, &e);
2001 if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
2002 winreg_delete_printer_key_internal(p->mem_ctx,
2003 get_session_info_system(),
2004 p->msg_ctx,
2005 lp_const_servicename(snum),
2006 "");
2009 result = delete_printer_handle(p, r->in.handle);
2011 return result;
2014 /*******************************************************************
2015 * static function to lookup the version id corresponding to an
2016 * long architecture string
2017 ******************************************************************/
2019 static const struct print_architecture_table_node archi_table[]= {
2021 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
2022 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
2023 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
2024 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
2025 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
2026 {"Windows IA64", SPL_ARCH_IA64, 3 },
2027 {"Windows x64", SPL_ARCH_X64, 3 },
2028 {NULL, "", -1 }
2031 static const int drv_cversion[] = {SPOOLSS_DRIVER_VERSION_9X,
2032 SPOOLSS_DRIVER_VERSION_NT35,
2033 SPOOLSS_DRIVER_VERSION_NT4,
2034 SPOOLSS_DRIVER_VERSION_200X,
2035 -1};
2037 static int get_version_id(const char *arch)
2039 int i;
2041 for (i=0; archi_table[i].long_archi != NULL; i++)
2043 if (strcmp(arch, archi_table[i].long_archi) == 0)
2044 return (archi_table[i].version);
2047 return -1;
2050 /****************************************************************
2051 _spoolss_DeletePrinterDriver
2052 ****************************************************************/
2054 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2055 struct spoolss_DeletePrinterDriver *r)
2058 struct spoolss_DriverInfo8 *info = NULL;
2059 int version;
2060 WERROR status;
2061 struct dcerpc_binding_handle *b;
2062 TALLOC_CTX *tmp_ctx = NULL;
2063 int i;
2064 bool found;
2066 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2067 and not a printer admin, then fail */
2069 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
2070 !security_token_has_privilege(p->session_info->security_token,
2071 SEC_PRIV_PRINT_OPERATOR)) {
2072 return WERR_ACCESS_DENIED;
2075 /* check that we have a valid driver name first */
2077 if ((version = get_version_id(r->in.architecture)) == -1) {
2078 return WERR_INVALID_ENVIRONMENT;
2081 tmp_ctx = talloc_new(p->mem_ctx);
2082 if (!tmp_ctx) {
2083 return WERR_NOMEM;
2086 status = winreg_printer_binding_handle(tmp_ctx,
2087 get_session_info_system(),
2088 p->msg_ctx,
2089 &b);
2090 if (!W_ERROR_IS_OK(status)) {
2091 goto done;
2094 for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2095 status = winreg_get_driver(tmp_ctx, b,
2096 r->in.architecture, r->in.driver,
2097 drv_cversion[i], &info);
2098 if (!W_ERROR_IS_OK(status)) {
2099 DEBUG(5, ("skipping del of driver with version %d\n",
2100 drv_cversion[i]));
2101 continue;
2103 found = true;
2105 if (printer_driver_in_use(tmp_ctx, b, info)) {
2106 status = WERR_PRINTER_DRIVER_IN_USE;
2107 goto done;
2110 status = winreg_del_driver(tmp_ctx, b, info, drv_cversion[i]);
2111 if (!W_ERROR_IS_OK(status)) {
2112 DEBUG(0, ("failed del of driver with version %d\n",
2113 drv_cversion[i]));
2114 goto done;
2117 if (found == false) {
2118 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2119 status = WERR_UNKNOWN_PRINTER_DRIVER;
2120 } else {
2121 status = WERR_OK;
2124 done:
2125 talloc_free(tmp_ctx);
2127 return status;
2130 static WERROR spoolss_dpd_version(TALLOC_CTX *mem_ctx,
2131 struct pipes_struct *p,
2132 struct spoolss_DeletePrinterDriverEx *r,
2133 struct dcerpc_binding_handle *b,
2134 struct spoolss_DriverInfo8 *info)
2136 WERROR status;
2137 bool delete_files;
2139 if (printer_driver_in_use(mem_ctx, b, info)) {
2140 status = WERR_PRINTER_DRIVER_IN_USE;
2141 goto done;
2145 * we have a couple of cases to consider.
2146 * (1) Are any files in use? If so and DPD_DELETE_ALL_FILES is set,
2147 * then the delete should fail if **any** files overlap with
2148 * other drivers
2149 * (2) If DPD_DELETE_UNUSED_FILES is set, then delete all
2150 * non-overlapping files
2151 * (3) If neither DPD_DELETE_ALL_FILES nor DPD_DELETE_UNUSED_FILES
2152 * are set, then do not delete any files
2153 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2156 delete_files = r->in.delete_flags
2157 & (DPD_DELETE_ALL_FILES | DPD_DELETE_UNUSED_FILES);
2160 if (delete_files) {
2161 bool in_use = printer_driver_files_in_use(mem_ctx, b, info);
2162 if (in_use && (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
2163 status = WERR_PRINTER_DRIVER_IN_USE;
2164 goto done;
2167 * printer_driver_files_in_use() has trimmed overlapping files
2168 * from info so they are not removed on DPD_DELETE_UNUSED_FILES
2173 status = winreg_del_driver(mem_ctx, b, info, info->version);
2174 if (!W_ERROR_IS_OK(status)) {
2175 goto done;
2179 * now delete any associated files if delete_files is
2180 * true. Even if this part failes, we return succes
2181 * because the driver doesn not exist any more
2183 if (delete_files) {
2184 delete_driver_files(p->session_info, info);
2187 done:
2188 return status;
2191 /****************************************************************
2192 _spoolss_DeletePrinterDriverEx
2193 ****************************************************************/
2195 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2196 struct spoolss_DeletePrinterDriverEx *r)
2198 struct spoolss_DriverInfo8 *info = NULL;
2199 WERROR status;
2200 struct dcerpc_binding_handle *b;
2201 TALLOC_CTX *tmp_ctx = NULL;
2202 int i;
2203 bool found;
2205 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2206 and not a printer admin, then fail */
2208 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
2209 !security_token_has_privilege(p->session_info->security_token,
2210 SEC_PRIV_PRINT_OPERATOR)) {
2211 return WERR_ACCESS_DENIED;
2214 /* check that we have a valid driver name first */
2215 if (get_version_id(r->in.architecture) == -1) {
2216 /* this is what NT returns */
2217 return WERR_INVALID_ENVIRONMENT;
2220 tmp_ctx = talloc_new(p->mem_ctx);
2221 if (!tmp_ctx) {
2222 return WERR_NOMEM;
2225 status = winreg_printer_binding_handle(tmp_ctx,
2226 get_session_info_system(),
2227 p->msg_ctx,
2228 &b);
2229 if (!W_ERROR_IS_OK(status)) {
2230 goto done;
2233 for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2234 if ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2235 && (drv_cversion[i] != r->in.version)) {
2236 continue;
2239 /* check if a driver with this version exists before delete */
2240 status = winreg_get_driver(tmp_ctx, b,
2241 r->in.architecture, r->in.driver,
2242 drv_cversion[i], &info);
2243 if (!W_ERROR_IS_OK(status)) {
2244 DEBUG(5, ("skipping del of driver with version %d\n",
2245 drv_cversion[i]));
2246 continue;
2248 found = true;
2250 status = spoolss_dpd_version(tmp_ctx, p, r, b, info);
2251 if (!W_ERROR_IS_OK(status)) {
2252 DEBUG(0, ("failed to delete driver with version %d\n",
2253 drv_cversion[i]));
2254 goto done;
2257 if (found == false) {
2258 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2259 status = WERR_UNKNOWN_PRINTER_DRIVER;
2260 } else {
2261 status = WERR_OK;
2264 done:
2265 talloc_free(tmp_ctx);
2266 return status;
2270 /********************************************************************
2271 GetPrinterData on a printer server Handle.
2272 ********************************************************************/
2274 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2275 const char *value,
2276 enum winreg_Type *type,
2277 union spoolss_PrinterData *data)
2279 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2281 if (!strcasecmp_m(value, "W3SvcInstalled")) {
2282 *type = REG_DWORD;
2283 SIVAL(&data->value, 0, 0x00);
2284 return WERR_OK;
2287 if (!strcasecmp_m(value, "BeepEnabled")) {
2288 *type = REG_DWORD;
2289 SIVAL(&data->value, 0, 0x00);
2290 return WERR_OK;
2293 if (!strcasecmp_m(value, "EventLog")) {
2294 *type = REG_DWORD;
2295 /* formally was 0x1b */
2296 SIVAL(&data->value, 0, 0x00);
2297 return WERR_OK;
2300 if (!strcasecmp_m(value, "NetPopup")) {
2301 *type = REG_DWORD;
2302 SIVAL(&data->value, 0, 0x00);
2303 return WERR_OK;
2306 if (!strcasecmp_m(value, "MajorVersion")) {
2307 *type = REG_DWORD;
2309 /* Windows NT 4.0 seems to not allow uploading of drivers
2310 to a server that reports 0x3 as the MajorVersion.
2311 need to investigate more how Win2k gets around this .
2312 -- jerry */
2314 if (RA_WINNT == get_remote_arch()) {
2315 SIVAL(&data->value, 0, 0x02);
2316 } else {
2317 SIVAL(&data->value, 0, 0x03);
2320 return WERR_OK;
2323 if (!strcasecmp_m(value, "MinorVersion")) {
2324 *type = REG_DWORD;
2325 SIVAL(&data->value, 0, 0x00);
2326 return WERR_OK;
2329 /* REG_BINARY
2330 * uint32_t size = 0x114
2331 * uint32_t major = 5
2332 * uint32_t minor = [0|1]
2333 * uint32_t build = [2195|2600]
2334 * extra unicode string = e.g. "Service Pack 3"
2336 if (!strcasecmp_m(value, "OSVersion")) {
2337 DATA_BLOB blob;
2338 enum ndr_err_code ndr_err;
2339 struct spoolss_OSVersion os;
2341 os.major = 5; /* Windows 2000 == 5.0 */
2342 os.minor = 0;
2343 os.build = 2195; /* build */
2344 os.extra_string = ""; /* leave extra string empty */
2346 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2347 (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2348 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2349 return WERR_GENERAL_FAILURE;
2352 *type = REG_BINARY;
2353 data->binary = blob;
2355 return WERR_OK;
2359 if (!strcasecmp_m(value, "DefaultSpoolDirectory")) {
2360 *type = REG_SZ;
2362 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2363 W_ERROR_HAVE_NO_MEMORY(data->string);
2365 return WERR_OK;
2368 if (!strcasecmp_m(value, "Architecture")) {
2369 *type = REG_SZ;
2370 data->string = talloc_strdup(mem_ctx,
2371 lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2372 W_ERROR_HAVE_NO_MEMORY(data->string);
2374 return WERR_OK;
2377 if (!strcasecmp_m(value, "DsPresent")) {
2378 *type = REG_DWORD;
2380 /* only show the publish check box if we are a
2381 member of a AD domain */
2383 if (lp_security() == SEC_ADS) {
2384 SIVAL(&data->value, 0, 0x01);
2385 } else {
2386 SIVAL(&data->value, 0, 0x00);
2388 return WERR_OK;
2391 if (!strcasecmp_m(value, "DNSMachineName")) {
2392 const char *hostname = get_mydnsfullname();
2394 if (!hostname) {
2395 return WERR_BADFILE;
2398 *type = REG_SZ;
2399 data->string = talloc_strdup(mem_ctx, hostname);
2400 W_ERROR_HAVE_NO_MEMORY(data->string);
2402 return WERR_OK;
2405 *type = REG_NONE;
2407 return WERR_INVALID_PARAM;
2410 /****************************************************************
2411 _spoolss_GetPrinterData
2412 ****************************************************************/
2414 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2415 struct spoolss_GetPrinterData *r)
2417 struct spoolss_GetPrinterDataEx r2;
2419 r2.in.handle = r->in.handle;
2420 r2.in.key_name = "PrinterDriverData";
2421 r2.in.value_name = r->in.value_name;
2422 r2.in.offered = r->in.offered;
2423 r2.out.type = r->out.type;
2424 r2.out.data = r->out.data;
2425 r2.out.needed = r->out.needed;
2427 return _spoolss_GetPrinterDataEx(p, &r2);
2430 /*********************************************************
2431 Connect to the client machine.
2432 **********************************************************/
2434 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2435 struct sockaddr_storage *client_ss, const char *remote_machine)
2437 NTSTATUS ret;
2438 struct cli_state *the_cli;
2439 struct sockaddr_storage rm_addr;
2440 char addr[INET6_ADDRSTRLEN];
2442 if ( is_zero_addr(client_ss) ) {
2443 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2444 remote_machine));
2445 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2446 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2447 return false;
2449 print_sockaddr(addr, sizeof(addr), &rm_addr);
2450 } else {
2451 rm_addr = *client_ss;
2452 print_sockaddr(addr, sizeof(addr), &rm_addr);
2453 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2454 addr));
2457 if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2458 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2459 addr));
2460 return false;
2463 /* setup the connection */
2464 ret = cli_full_connection( &the_cli, lp_netbios_name(), remote_machine,
2465 &rm_addr, 0, "IPC$", "IPC",
2466 "", /* username */
2467 "", /* domain */
2468 "", /* password */
2469 0, lp_client_signing());
2471 if ( !NT_STATUS_IS_OK( ret ) ) {
2472 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2473 remote_machine ));
2474 return false;
2477 if ( smbXcli_conn_protocol(the_cli->conn) != PROTOCOL_NT1 ) {
2478 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2479 cli_shutdown(the_cli);
2480 return false;
2484 * Ok - we have an anonymous connection to the IPC$ share.
2485 * Now start the NT Domain stuff :-).
2488 ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2489 if (!NT_STATUS_IS_OK(ret)) {
2490 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2491 remote_machine, nt_errstr(ret)));
2492 cli_shutdown(the_cli);
2493 return false;
2496 return true;
2499 /***************************************************************************
2500 Connect to the client.
2501 ****************************************************************************/
2503 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2504 uint32_t localprinter,
2505 enum winreg_Type type,
2506 struct policy_handle *handle,
2507 struct notify_back_channel **_chan,
2508 struct sockaddr_storage *client_ss,
2509 struct messaging_context *msg_ctx)
2511 WERROR result;
2512 NTSTATUS status;
2513 struct notify_back_channel *chan;
2515 for (chan = back_channels; chan; chan = chan->next) {
2516 if (memcmp(&chan->client_address, client_ss,
2517 sizeof(struct sockaddr_storage)) == 0) {
2518 break;
2523 * If it's the first connection, contact the client
2524 * and connect to the IPC$ share anonymously
2526 if (!chan) {
2527 fstring unix_printer;
2529 /* the +2 is to strip the leading 2 backslashs */
2530 fstrcpy(unix_printer, printer + 2);
2532 chan = talloc_zero(NULL, struct notify_back_channel);
2533 if (!chan) {
2534 return false;
2536 chan->client_address = *client_ss;
2538 if (!spoolss_connect_to_client(&chan->cli_pipe, client_ss, unix_printer)) {
2539 TALLOC_FREE(chan);
2540 return false;
2543 DLIST_ADD(back_channels, chan);
2545 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2546 receive_notify2_message_list);
2549 if (chan->cli_pipe == NULL ||
2550 chan->cli_pipe->binding_handle == NULL) {
2551 DEBUG(0, ("srv_spoolss_replyopenprinter: error - "
2552 "NULL %s for printer %s\n",
2553 chan->cli_pipe == NULL ?
2554 "chan->cli_pipe" : "chan->cli_pipe->binding_handle",
2555 printer));
2556 return false;
2560 * Tell the specific printing tdb we want messages for this printer
2561 * by registering our PID.
2564 if (!print_notify_register_pid(snum)) {
2565 DEBUG(0, ("Failed to register our pid for printer %s\n",
2566 printer));
2569 status = dcerpc_spoolss_ReplyOpenPrinter(chan->cli_pipe->binding_handle,
2570 talloc_tos(),
2571 printer,
2572 localprinter,
2573 type,
2575 NULL,
2576 handle,
2577 &result);
2578 if (!NT_STATUS_IS_OK(status)) {
2579 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2580 result = ntstatus_to_werror(status);
2581 } else if (!W_ERROR_IS_OK(result)) {
2582 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2585 chan->active_connections++;
2586 *_chan = chan;
2588 return (W_ERROR_IS_OK(result));
2591 /****************************************************************
2592 ****************************************************************/
2594 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2595 const struct spoolss_NotifyOption *r)
2597 struct spoolss_NotifyOption *option;
2598 uint32_t i,k;
2600 if (!r) {
2601 return NULL;
2604 option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2605 if (!option) {
2606 return NULL;
2609 *option = *r;
2611 if (!option->count) {
2612 return option;
2615 option->types = talloc_zero_array(option,
2616 struct spoolss_NotifyOptionType, option->count);
2617 if (!option->types) {
2618 talloc_free(option);
2619 return NULL;
2622 for (i=0; i < option->count; i++) {
2623 option->types[i] = r->types[i];
2625 if (option->types[i].count) {
2626 option->types[i].fields = talloc_zero_array(option,
2627 union spoolss_Field, option->types[i].count);
2628 if (!option->types[i].fields) {
2629 talloc_free(option);
2630 return NULL;
2632 for (k=0; k<option->types[i].count; k++) {
2633 option->types[i].fields[k] =
2634 r->types[i].fields[k];
2639 return option;
2642 /****************************************************************
2643 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2645 * before replying OK: status=0 a rpc call is made to the workstation
2646 * asking ReplyOpenPrinter
2648 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2649 * called from api_spoolss_rffpcnex
2650 ****************************************************************/
2652 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2653 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2655 int snum = -1;
2656 struct spoolss_NotifyOption *option = r->in.notify_options;
2657 struct sockaddr_storage client_ss;
2658 ssize_t client_len;
2660 /* store the notify value in the printer struct */
2662 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2664 if (!Printer) {
2665 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2666 "Invalid handle (%s:%u:%u).\n",
2667 OUR_HANDLE(r->in.handle)));
2668 return WERR_BADFID;
2671 Printer->notify.flags = r->in.flags;
2672 Printer->notify.options = r->in.options;
2673 Printer->notify.printerlocal = r->in.printer_local;
2674 Printer->notify.msg_ctx = p->msg_ctx;
2676 TALLOC_FREE(Printer->notify.option);
2677 Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2679 fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2681 /* Connect to the client machine and send a ReplyOpenPrinter */
2683 if ( Printer->printer_type == SPLHND_SERVER)
2684 snum = -1;
2685 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2686 !get_printer_snum(p, r->in.handle, &snum, NULL) )
2687 return WERR_BADFID;
2689 DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2690 "remote_address is %s\n",
2691 tsocket_address_string(p->remote_address, p->mem_ctx)));
2693 if (!lp_print_notify_backchannel(snum)) {
2694 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2695 "backchannel disabled\n"));
2696 return WERR_SERVER_UNAVAILABLE;
2699 client_len = tsocket_address_bsd_sockaddr(p->remote_address,
2700 (struct sockaddr *) &client_ss,
2701 sizeof(struct sockaddr_storage));
2702 if (client_len < 0) {
2703 return WERR_NOMEM;
2706 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2707 Printer->notify.printerlocal, REG_SZ,
2708 &Printer->notify.cli_hnd,
2709 &Printer->notify.cli_chan,
2710 &client_ss, p->msg_ctx)) {
2711 return WERR_SERVER_UNAVAILABLE;
2714 return WERR_OK;
2717 /*******************************************************************
2718 * fill a notify_info_data with the servername
2719 ********************************************************************/
2721 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2722 int snum,
2723 struct spoolss_Notify *data,
2724 print_queue_struct *queue,
2725 struct spoolss_PrinterInfo2 *pinfo2,
2726 TALLOC_CTX *mem_ctx)
2728 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2731 /*******************************************************************
2732 * fill a notify_info_data with the printername (not including the servername).
2733 ********************************************************************/
2735 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2736 int snum,
2737 struct spoolss_Notify *data,
2738 print_queue_struct *queue,
2739 struct spoolss_PrinterInfo2 *pinfo2,
2740 TALLOC_CTX *mem_ctx)
2742 /* the notify name should not contain the \\server\ part */
2743 const char *p = strrchr(pinfo2->printername, '\\');
2745 if (!p) {
2746 p = pinfo2->printername;
2747 } else {
2748 p++;
2751 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2754 /*******************************************************************
2755 * fill a notify_info_data with the servicename
2756 ********************************************************************/
2758 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2759 int snum,
2760 struct spoolss_Notify *data,
2761 print_queue_struct *queue,
2762 struct spoolss_PrinterInfo2 *pinfo2,
2763 TALLOC_CTX *mem_ctx)
2765 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(talloc_tos(), snum));
2768 /*******************************************************************
2769 * fill a notify_info_data with the port name
2770 ********************************************************************/
2772 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2773 int snum,
2774 struct spoolss_Notify *data,
2775 print_queue_struct *queue,
2776 struct spoolss_PrinterInfo2 *pinfo2,
2777 TALLOC_CTX *mem_ctx)
2779 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2782 /*******************************************************************
2783 * fill a notify_info_data with the printername
2784 * but it doesn't exist, have to see what to do
2785 ********************************************************************/
2787 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2788 int snum,
2789 struct spoolss_Notify *data,
2790 print_queue_struct *queue,
2791 struct spoolss_PrinterInfo2 *pinfo2,
2792 TALLOC_CTX *mem_ctx)
2794 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2797 /*******************************************************************
2798 * fill a notify_info_data with the comment
2799 ********************************************************************/
2801 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2802 int snum,
2803 struct spoolss_Notify *data,
2804 print_queue_struct *queue,
2805 struct spoolss_PrinterInfo2 *pinfo2,
2806 TALLOC_CTX *mem_ctx)
2808 const char *p;
2810 if (*pinfo2->comment == '\0') {
2811 p = lp_comment(talloc_tos(), snum);
2812 } else {
2813 p = pinfo2->comment;
2816 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2819 /*******************************************************************
2820 * fill a notify_info_data with the comment
2821 * location = "Room 1, floor 2, building 3"
2822 ********************************************************************/
2824 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2825 int snum,
2826 struct spoolss_Notify *data,
2827 print_queue_struct *queue,
2828 struct spoolss_PrinterInfo2 *pinfo2,
2829 TALLOC_CTX *mem_ctx)
2831 const char *loc = pinfo2->location;
2832 NTSTATUS status;
2834 status = printer_list_get_printer(mem_ctx,
2835 pinfo2->sharename,
2836 NULL,
2837 &loc,
2838 NULL);
2839 if (NT_STATUS_IS_OK(status)) {
2840 if (loc == NULL) {
2841 loc = pinfo2->location;
2845 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, loc);
2848 /*******************************************************************
2849 * fill a notify_info_data with the device mode
2850 * jfm:xxxx don't to it for know but that's a real problem !!!
2851 ********************************************************************/
2853 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2854 int snum,
2855 struct spoolss_Notify *data,
2856 print_queue_struct *queue,
2857 struct spoolss_PrinterInfo2 *pinfo2,
2858 TALLOC_CTX *mem_ctx)
2860 /* for a dummy implementation we have to zero the fields */
2861 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2864 /*******************************************************************
2865 * fill a notify_info_data with the separator file name
2866 ********************************************************************/
2868 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2869 int snum,
2870 struct spoolss_Notify *data,
2871 print_queue_struct *queue,
2872 struct spoolss_PrinterInfo2 *pinfo2,
2873 TALLOC_CTX *mem_ctx)
2875 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2878 /*******************************************************************
2879 * fill a notify_info_data with the print processor
2880 * jfm:xxxx return always winprint to indicate we don't do anything to it
2881 ********************************************************************/
2883 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2884 int snum,
2885 struct spoolss_Notify *data,
2886 print_queue_struct *queue,
2887 struct spoolss_PrinterInfo2 *pinfo2,
2888 TALLOC_CTX *mem_ctx)
2890 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2893 /*******************************************************************
2894 * fill a notify_info_data with the print processor options
2895 * jfm:xxxx send an empty string
2896 ********************************************************************/
2898 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2899 int snum,
2900 struct spoolss_Notify *data,
2901 print_queue_struct *queue,
2902 struct spoolss_PrinterInfo2 *pinfo2,
2903 TALLOC_CTX *mem_ctx)
2905 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2908 /*******************************************************************
2909 * fill a notify_info_data with the data type
2910 * jfm:xxxx always send RAW as data type
2911 ********************************************************************/
2913 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2914 int snum,
2915 struct spoolss_Notify *data,
2916 print_queue_struct *queue,
2917 struct spoolss_PrinterInfo2 *pinfo2,
2918 TALLOC_CTX *mem_ctx)
2920 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2923 /*******************************************************************
2924 * fill a notify_info_data with the security descriptor
2925 * jfm:xxxx send an null pointer to say no security desc
2926 * have to implement security before !
2927 ********************************************************************/
2929 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2930 int snum,
2931 struct spoolss_Notify *data,
2932 print_queue_struct *queue,
2933 struct spoolss_PrinterInfo2 *pinfo2,
2934 TALLOC_CTX *mem_ctx)
2936 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
2939 /*******************************************************************
2940 * fill a notify_info_data with the attributes
2941 * jfm:xxxx a samba printer is always shared
2942 ********************************************************************/
2944 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2945 int snum,
2946 struct spoolss_Notify *data,
2947 print_queue_struct *queue,
2948 struct spoolss_PrinterInfo2 *pinfo2,
2949 TALLOC_CTX *mem_ctx)
2951 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2954 /*******************************************************************
2955 * fill a notify_info_data with the priority
2956 ********************************************************************/
2958 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
2959 int snum,
2960 struct spoolss_Notify *data,
2961 print_queue_struct *queue,
2962 struct spoolss_PrinterInfo2 *pinfo2,
2963 TALLOC_CTX *mem_ctx)
2965 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
2968 /*******************************************************************
2969 * fill a notify_info_data with the default priority
2970 ********************************************************************/
2972 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
2973 int snum,
2974 struct spoolss_Notify *data,
2975 print_queue_struct *queue,
2976 struct spoolss_PrinterInfo2 *pinfo2,
2977 TALLOC_CTX *mem_ctx)
2979 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
2982 /*******************************************************************
2983 * fill a notify_info_data with the start time
2984 ********************************************************************/
2986 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
2987 int snum,
2988 struct spoolss_Notify *data,
2989 print_queue_struct *queue,
2990 struct spoolss_PrinterInfo2 *pinfo2,
2991 TALLOC_CTX *mem_ctx)
2993 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
2996 /*******************************************************************
2997 * fill a notify_info_data with the until time
2998 ********************************************************************/
3000 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3001 int snum,
3002 struct spoolss_Notify *data,
3003 print_queue_struct *queue,
3004 struct spoolss_PrinterInfo2 *pinfo2,
3005 TALLOC_CTX *mem_ctx)
3007 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3010 /*******************************************************************
3011 * fill a notify_info_data with the status
3012 ********************************************************************/
3014 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3015 int snum,
3016 struct spoolss_Notify *data,
3017 print_queue_struct *queue,
3018 struct spoolss_PrinterInfo2 *pinfo2,
3019 TALLOC_CTX *mem_ctx)
3021 print_status_struct status;
3023 print_queue_length(msg_ctx, snum, &status);
3024 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3027 /*******************************************************************
3028 * fill a notify_info_data with the number of jobs queued
3029 ********************************************************************/
3031 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3032 int snum,
3033 struct spoolss_Notify *data,
3034 print_queue_struct *queue,
3035 struct spoolss_PrinterInfo2 *pinfo2,
3036 TALLOC_CTX *mem_ctx)
3038 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3039 data, print_queue_length(msg_ctx, snum, NULL));
3042 /*******************************************************************
3043 * fill a notify_info_data with the average ppm
3044 ********************************************************************/
3046 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3047 int snum,
3048 struct spoolss_Notify *data,
3049 print_queue_struct *queue,
3050 struct spoolss_PrinterInfo2 *pinfo2,
3051 TALLOC_CTX *mem_ctx)
3053 /* always respond 8 pages per minutes */
3054 /* a little hard ! */
3055 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3058 /*******************************************************************
3059 * fill a notify_info_data with username
3060 ********************************************************************/
3062 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3063 int snum,
3064 struct spoolss_Notify *data,
3065 print_queue_struct *queue,
3066 struct spoolss_PrinterInfo2 *pinfo2,
3067 TALLOC_CTX *mem_ctx)
3069 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3072 /*******************************************************************
3073 * fill a notify_info_data with job status
3074 ********************************************************************/
3076 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3077 int snum,
3078 struct spoolss_Notify *data,
3079 print_queue_struct *queue,
3080 struct spoolss_PrinterInfo2 *pinfo2,
3081 TALLOC_CTX *mem_ctx)
3083 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3086 /*******************************************************************
3087 * fill a notify_info_data with job name
3088 ********************************************************************/
3090 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3091 int snum,
3092 struct spoolss_Notify *data,
3093 print_queue_struct *queue,
3094 struct spoolss_PrinterInfo2 *pinfo2,
3095 TALLOC_CTX *mem_ctx)
3097 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3100 /*******************************************************************
3101 * fill a notify_info_data with job status
3102 ********************************************************************/
3104 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3105 int snum,
3106 struct spoolss_Notify *data,
3107 print_queue_struct *queue,
3108 struct spoolss_PrinterInfo2 *pinfo2,
3109 TALLOC_CTX *mem_ctx)
3112 * Now we're returning job status codes we just return a "" here. JRA.
3115 const char *p = "";
3117 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3118 p = "unknown";
3120 switch (queue->status) {
3121 case LPQ_QUEUED:
3122 p = "Queued";
3123 break;
3124 case LPQ_PAUSED:
3125 p = ""; /* NT provides the paused string */
3126 break;
3127 case LPQ_SPOOLING:
3128 p = "Spooling";
3129 break;
3130 case LPQ_PRINTING:
3131 p = "Printing";
3132 break;
3134 #endif /* NO LONGER NEEDED. */
3136 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3139 /*******************************************************************
3140 * fill a notify_info_data with job time
3141 ********************************************************************/
3143 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3144 int snum,
3145 struct spoolss_Notify *data,
3146 print_queue_struct *queue,
3147 struct spoolss_PrinterInfo2 *pinfo2,
3148 TALLOC_CTX *mem_ctx)
3150 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3153 /*******************************************************************
3154 * fill a notify_info_data with job size
3155 ********************************************************************/
3157 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3158 int snum,
3159 struct spoolss_Notify *data,
3160 print_queue_struct *queue,
3161 struct spoolss_PrinterInfo2 *pinfo2,
3162 TALLOC_CTX *mem_ctx)
3164 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3167 /*******************************************************************
3168 * fill a notify_info_data with page info
3169 ********************************************************************/
3170 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3171 int snum,
3172 struct spoolss_Notify *data,
3173 print_queue_struct *queue,
3174 struct spoolss_PrinterInfo2 *pinfo2,
3175 TALLOC_CTX *mem_ctx)
3177 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3180 /*******************************************************************
3181 * fill a notify_info_data with pages printed info.
3182 ********************************************************************/
3183 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3184 int snum,
3185 struct spoolss_Notify *data,
3186 print_queue_struct *queue,
3187 struct spoolss_PrinterInfo2 *pinfo2,
3188 TALLOC_CTX *mem_ctx)
3190 /* Add code when back-end tracks this */
3191 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3194 /*******************************************************************
3195 Fill a notify_info_data with job position.
3196 ********************************************************************/
3198 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3199 int snum,
3200 struct spoolss_Notify *data,
3201 print_queue_struct *queue,
3202 struct spoolss_PrinterInfo2 *pinfo2,
3203 TALLOC_CTX *mem_ctx)
3205 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->sysjob);
3208 /*******************************************************************
3209 Fill a notify_info_data with submitted time.
3210 ********************************************************************/
3212 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3213 int snum,
3214 struct spoolss_Notify *data,
3215 print_queue_struct *queue,
3216 struct spoolss_PrinterInfo2 *pinfo2,
3217 TALLOC_CTX *mem_ctx)
3219 data->data.string.string = NULL;
3220 data->data.string.size = 0;
3222 init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3223 &data->data.string.string,
3224 &data->data.string.size);
3228 struct s_notify_info_data_table
3230 enum spoolss_NotifyType type;
3231 uint16_t field;
3232 const char *name;
3233 enum spoolss_NotifyTable variable_type;
3234 void (*fn) (struct messaging_context *msg_ctx,
3235 int snum, struct spoolss_Notify *data,
3236 print_queue_struct *queue,
3237 struct spoolss_PrinterInfo2 *pinfo2,
3238 TALLOC_CTX *mem_ctx);
3241 /* A table describing the various print notification constants and
3242 whether the notification data is a pointer to a variable sized
3243 buffer, a one value uint32_t or a two value uint32_t. */
3245 static const struct s_notify_info_data_table notify_info_data_table[] =
3247 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3248 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3249 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
3250 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3251 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3252 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
3253 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
3254 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3255 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
3256 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3257 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3258 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3259 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
3260 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
3261 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3262 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
3263 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3264 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3265 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
3266 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
3267 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
3268 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
3269 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
3270 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3271 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
3272 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3273 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINTER_NAME, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3274 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_MACHINE_NAME, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3275 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PORT_NAME, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3276 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_USER_NAME, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3277 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_NOTIFY_NAME, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3278 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DATATYPE, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3279 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINT_PROCESSOR, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3280 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PARAMETERS, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3281 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DRIVER_NAME, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3282 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DEVMODE, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3283 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
3284 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS_STRING, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
3285 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
3286 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DOCUMENT, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
3287 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRIORITY, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3288 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_POSITION, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
3289 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SUBMITTED, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
3290 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_START_TIME, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3291 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_UNTIL_TIME, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3292 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TIME, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
3293 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_PAGES, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
3294 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PAGES_PRINTED, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
3295 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_BYTES, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
3298 /*******************************************************************
3299 Return the variable_type of info_data structure.
3300 ********************************************************************/
3302 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3303 uint16_t field)
3305 int i=0;
3307 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3308 if ( (notify_info_data_table[i].type == type) &&
3309 (notify_info_data_table[i].field == field) ) {
3310 return notify_info_data_table[i].variable_type;
3314 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3316 return (enum spoolss_NotifyTable) 0;
3319 /****************************************************************************
3320 ****************************************************************************/
3322 static bool search_notify(enum spoolss_NotifyType type,
3323 uint16_t field,
3324 int *value)
3326 int i;
3328 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3329 if (notify_info_data_table[i].type == type &&
3330 notify_info_data_table[i].field == field &&
3331 notify_info_data_table[i].fn != NULL) {
3332 *value = i;
3333 return true;
3337 return false;
3340 /****************************************************************************
3341 ****************************************************************************/
3343 static void construct_info_data(struct spoolss_Notify *info_data,
3344 enum spoolss_NotifyType type,
3345 uint16_t field, int id)
3347 info_data->type = type;
3348 info_data->field.field = field;
3349 info_data->variable_type = variable_type_of_notify_info_data(type, field);
3350 info_data->job_id = id;
3353 /*******************************************************************
3355 * fill a notify_info struct with info asked
3357 ********************************************************************/
3359 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3360 struct printer_handle *print_hnd,
3361 struct spoolss_NotifyInfo *info,
3362 struct spoolss_PrinterInfo2 *pinfo2,
3363 int snum,
3364 const struct spoolss_NotifyOptionType *option_type,
3365 uint32_t id,
3366 TALLOC_CTX *mem_ctx)
3368 int field_num,j;
3369 enum spoolss_NotifyType type;
3370 uint16_t field;
3372 struct spoolss_Notify *current_data;
3374 type = option_type->type;
3376 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3377 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3378 option_type->count, lp_servicename(talloc_tos(), snum)));
3380 for(field_num=0; field_num < option_type->count; field_num++) {
3381 field = option_type->fields[field_num].field;
3383 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3385 if (!search_notify(type, field, &j) )
3386 continue;
3388 info->notifies = talloc_realloc(info, info->notifies,
3389 struct spoolss_Notify,
3390 info->count + 1);
3391 if (info->notifies == NULL) {
3392 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3393 return false;
3396 current_data = &info->notifies[info->count];
3398 construct_info_data(current_data, type, field, id);
3400 DEBUG(10, ("construct_notify_printer_info: "
3401 "calling [%s] snum=%d printername=[%s])\n",
3402 notify_info_data_table[j].name, snum,
3403 pinfo2->printername));
3405 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3406 NULL, pinfo2, mem_ctx);
3408 info->count++;
3411 return true;
3414 /*******************************************************************
3416 * fill a notify_info struct with info asked
3418 ********************************************************************/
3420 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3421 print_queue_struct *queue,
3422 struct spoolss_NotifyInfo *info,
3423 struct spoolss_PrinterInfo2 *pinfo2,
3424 int snum,
3425 const struct spoolss_NotifyOptionType *option_type,
3426 uint32_t id,
3427 TALLOC_CTX *mem_ctx)
3429 int field_num,j;
3430 enum spoolss_NotifyType type;
3431 uint16_t field;
3432 struct spoolss_Notify *current_data;
3434 DEBUG(4,("construct_notify_jobs_info\n"));
3436 type = option_type->type;
3438 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3439 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3440 option_type->count));
3442 for(field_num=0; field_num<option_type->count; field_num++) {
3443 field = option_type->fields[field_num].field;
3445 if (!search_notify(type, field, &j) )
3446 continue;
3448 info->notifies = talloc_realloc(info, info->notifies,
3449 struct spoolss_Notify,
3450 info->count + 1);
3451 if (info->notifies == NULL) {
3452 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3453 return false;
3456 current_data=&(info->notifies[info->count]);
3458 construct_info_data(current_data, type, field, id);
3459 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3460 queue, pinfo2, mem_ctx);
3461 info->count++;
3464 return true;
3468 * JFM: The enumeration is not that simple, it's even non obvious.
3470 * let's take an example: I want to monitor the PRINTER SERVER for
3471 * the printer's name and the number of jobs currently queued.
3472 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3473 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3475 * I have 3 printers on the back of my server.
3477 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3478 * structures.
3479 * Number Data Id
3480 * 1 printer 1 name 1
3481 * 2 printer 1 cjob 1
3482 * 3 printer 2 name 2
3483 * 4 printer 2 cjob 2
3484 * 5 printer 3 name 3
3485 * 6 printer 3 name 3
3487 * that's the print server case, the printer case is even worse.
3490 /*******************************************************************
3492 * enumerate all printers on the printserver
3493 * fill a notify_info struct with info asked
3495 ********************************************************************/
3497 static WERROR printserver_notify_info(struct pipes_struct *p,
3498 struct policy_handle *hnd,
3499 struct spoolss_NotifyInfo *info,
3500 TALLOC_CTX *mem_ctx)
3502 int snum;
3503 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3504 int n_services=lp_numservices();
3505 int i;
3506 struct spoolss_NotifyOption *option;
3507 struct spoolss_NotifyOptionType option_type;
3508 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3509 WERROR result;
3511 DEBUG(4,("printserver_notify_info\n"));
3513 if (!Printer)
3514 return WERR_BADFID;
3516 option = Printer->notify.option;
3518 info->version = 2;
3519 info->notifies = NULL;
3520 info->count = 0;
3522 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3523 sending a ffpcn() request first */
3525 if ( !option )
3526 return WERR_BADFID;
3528 for (i=0; i<option->count; i++) {
3529 option_type = option->types[i];
3531 if (option_type.type != PRINTER_NOTIFY_TYPE)
3532 continue;
3534 for (snum = 0; snum < n_services; snum++) {
3535 if (!lp_browseable(snum) ||
3536 !lp_snum_ok(snum) ||
3537 !lp_print_ok(snum)) {
3538 continue; /* skip */
3541 /* Maybe we should use the SYSTEM session_info here... */
3542 result = winreg_get_printer_internal(mem_ctx,
3543 get_session_info_system(),
3544 p->msg_ctx,
3545 lp_servicename(talloc_tos(), snum),
3546 &pinfo2);
3547 if (!W_ERROR_IS_OK(result)) {
3548 DEBUG(4, ("printserver_notify_info: "
3549 "Failed to get printer [%s]\n",
3550 lp_servicename(talloc_tos(), snum)));
3551 continue;
3555 construct_notify_printer_info(p->msg_ctx,
3556 Printer, info,
3557 pinfo2, snum,
3558 &option_type, snum,
3559 mem_ctx);
3561 TALLOC_FREE(pinfo2);
3565 #if 0
3567 * Debugging information, don't delete.
3570 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3571 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3572 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3574 for (i=0; i<info->count; i++) {
3575 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3576 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3577 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3579 #endif
3581 return WERR_OK;
3584 /*******************************************************************
3586 * fill a notify_info struct with info asked
3588 ********************************************************************/
3590 static WERROR printer_notify_info(struct pipes_struct *p,
3591 struct policy_handle *hnd,
3592 struct spoolss_NotifyInfo *info,
3593 TALLOC_CTX *mem_ctx)
3595 int snum;
3596 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3597 int i;
3598 uint32_t id;
3599 struct spoolss_NotifyOption *option;
3600 struct spoolss_NotifyOptionType option_type;
3601 int count,j;
3602 print_queue_struct *queue=NULL;
3603 print_status_struct status;
3604 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3605 WERROR result;
3607 DEBUG(4,("printer_notify_info\n"));
3609 if (!Printer)
3610 return WERR_BADFID;
3612 option = Printer->notify.option;
3613 id = 0x0;
3615 info->version = 2;
3616 info->notifies = NULL;
3617 info->count = 0;
3619 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3620 sending a ffpcn() request first */
3622 if ( !option )
3623 return WERR_BADFID;
3625 if (!get_printer_snum(p, hnd, &snum, NULL)) {
3626 return WERR_BADFID;
3629 /* Maybe we should use the SYSTEM session_info here... */
3630 result = winreg_get_printer_internal(mem_ctx,
3631 get_session_info_system(),
3632 p->msg_ctx,
3633 lp_servicename(talloc_tos(), snum), &pinfo2);
3634 if (!W_ERROR_IS_OK(result)) {
3635 return WERR_BADFID;
3639 * When sending a PRINTER_NOTIFY_FIELD_SERVER_NAME we should send the
3640 * correct servername.
3642 pinfo2->servername = talloc_strdup(pinfo2, Printer->servername);
3643 if (pinfo2->servername == NULL) {
3644 return WERR_NOMEM;
3647 for (i=0; i<option->count; i++) {
3648 option_type = option->types[i];
3650 switch (option_type.type) {
3651 case PRINTER_NOTIFY_TYPE:
3652 if (construct_notify_printer_info(p->msg_ctx,
3653 Printer, info,
3654 pinfo2, snum,
3655 &option_type, id,
3656 mem_ctx)) {
3657 id--;
3659 break;
3661 case JOB_NOTIFY_TYPE:
3663 count = print_queue_status(p->msg_ctx, snum, &queue,
3664 &status);
3666 for (j=0; j<count; j++) {
3667 construct_notify_jobs_info(p->msg_ctx,
3668 &queue[j], info,
3669 pinfo2, snum,
3670 &option_type,
3671 queue[j].sysjob,
3672 mem_ctx);
3675 SAFE_FREE(queue);
3676 break;
3681 * Debugging information, don't delete.
3684 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3685 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3686 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3688 for (i=0; i<info->count; i++) {
3689 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3690 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3691 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3695 talloc_free(pinfo2);
3696 return WERR_OK;
3699 /****************************************************************
3700 _spoolss_RouterRefreshPrinterChangeNotify
3701 ****************************************************************/
3703 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3704 struct spoolss_RouterRefreshPrinterChangeNotify *r)
3706 struct spoolss_NotifyInfo *info;
3708 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3709 WERROR result = WERR_BADFID;
3711 /* we always have a spoolss_NotifyInfo struct */
3712 info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3713 if (!info) {
3714 result = WERR_NOMEM;
3715 goto done;
3718 *r->out.info = info;
3720 if (!Printer) {
3721 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3722 "Invalid handle (%s:%u:%u).\n",
3723 OUR_HANDLE(r->in.handle)));
3724 goto done;
3727 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3730 * We are now using the change value, and
3731 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3732 * I don't have a global notification system, I'm sending back all the
3733 * information even when _NOTHING_ has changed.
3736 /* We need to keep track of the change value to send back in
3737 RRPCN replies otherwise our updates are ignored. */
3739 Printer->notify.fnpcn = true;
3741 if (Printer->notify.cli_chan != NULL &&
3742 Printer->notify.cli_chan->active_connections > 0) {
3743 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3744 "Saving change value in request [%x]\n",
3745 r->in.change_low));
3746 Printer->notify.change = r->in.change_low;
3749 /* just ignore the spoolss_NotifyOption */
3751 switch (Printer->printer_type) {
3752 case SPLHND_SERVER:
3753 result = printserver_notify_info(p, r->in.handle,
3754 info, p->mem_ctx);
3755 break;
3757 case SPLHND_PRINTER:
3758 result = printer_notify_info(p, r->in.handle,
3759 info, p->mem_ctx);
3760 break;
3763 Printer->notify.fnpcn = false;
3765 done:
3766 return result;
3769 /********************************************************************
3770 ********************************************************************/
3772 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3773 const char *servername,
3774 const char *printername,
3775 const char **printername_p)
3777 /* FIXME: add lp_force_printername() */
3779 if (servername == NULL) {
3780 *printername_p = talloc_strdup(mem_ctx, printername);
3781 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3782 return WERR_OK;
3785 if (servername[0] == '\\' && servername[1] == '\\') {
3786 servername += 2;
3789 *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3790 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3792 return WERR_OK;
3795 /********************************************************************
3796 ********************************************************************/
3798 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3799 const char *printername)
3801 if (dm == NULL) {
3802 return;
3805 dm->devicename = talloc_strndup(dm, printername,
3806 MIN(strlen(printername), 31));
3809 /********************************************************************
3810 * construct_printer_info_0
3811 * fill a printer_info_0 struct
3812 ********************************************************************/
3814 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3815 const struct auth_session_info *session_info,
3816 struct messaging_context *msg_ctx,
3817 struct spoolss_PrinterInfo2 *info2,
3818 const char *servername,
3819 struct spoolss_PrinterInfo0 *r,
3820 int snum)
3822 int count;
3823 struct printer_session_counter *session_counter;
3824 struct timeval setuptime;
3825 print_status_struct status;
3826 WERROR result;
3828 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3829 if (!W_ERROR_IS_OK(result)) {
3830 return result;
3833 if (servername) {
3834 r->servername = talloc_strdup(mem_ctx, servername);
3835 W_ERROR_HAVE_NO_MEMORY(r->servername);
3836 } else {
3837 r->servername = NULL;
3840 count = print_queue_length(msg_ctx, snum, &status);
3842 /* check if we already have a counter for this printer */
3843 for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3844 if (session_counter->snum == snum)
3845 break;
3848 /* it's the first time, add it to the list */
3849 if (session_counter == NULL) {
3850 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3851 W_ERROR_HAVE_NO_MEMORY(session_counter);
3852 session_counter->snum = snum;
3853 session_counter->counter = 0;
3854 DLIST_ADD(counter_list, session_counter);
3857 /* increment it */
3858 session_counter->counter++;
3860 r->cjobs = count;
3861 r->total_jobs = 0;
3862 r->total_bytes = 0;
3864 get_startup_time(&setuptime);
3865 init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3867 /* JFM:
3868 * the global_counter should be stored in a TDB as it's common to all the clients
3869 * and should be zeroed on samba startup
3871 r->global_counter = session_counter->counter;
3872 r->total_pages = 0;
3873 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3874 SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3875 SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3876 r->free_build = SPOOLSS_RELEASE_BUILD;
3877 r->spooling = 0;
3878 r->max_spooling = 0;
3879 r->session_counter = session_counter->counter;
3880 r->num_error_out_of_paper = 0x0;
3881 r->num_error_not_ready = 0x0; /* number of print failure */
3882 r->job_error = 0x0;
3883 r->number_of_processors = 0x1;
3884 r->processor_type = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3885 r->high_part_total_bytes = 0x0;
3887 /* ChangeID in milliseconds*/
3888 winreg_printer_get_changeid_internal(mem_ctx, session_info, msg_ctx,
3889 info2->sharename, &r->change_id);
3891 r->last_error = WERR_OK;
3892 r->status = nt_printq_status(status.status);
3893 r->enumerate_network_printers = 0x0;
3894 r->c_setprinter = 0x0;
3895 r->processor_architecture = PROCESSOR_ARCHITECTURE_INTEL;
3896 r->processor_level = 0x6; /* 6 ???*/
3897 r->ref_ic = 0;
3898 r->reserved2 = 0;
3899 r->reserved3 = 0;
3901 return WERR_OK;
3905 /********************************************************************
3906 * construct_printer_info1
3907 * fill a spoolss_PrinterInfo1 struct
3908 ********************************************************************/
3910 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3911 const struct spoolss_PrinterInfo2 *info2,
3912 uint32_t flags,
3913 const char *servername,
3914 struct spoolss_PrinterInfo1 *r,
3915 int snum)
3917 WERROR result;
3919 r->flags = flags;
3921 if (info2->comment == NULL || info2->comment[0] == '\0') {
3922 r->comment = lp_comment(mem_ctx, snum);
3923 } else {
3924 r->comment = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3926 W_ERROR_HAVE_NO_MEMORY(r->comment);
3928 result = create_printername(mem_ctx, servername, info2->printername, &r->name);
3929 if (!W_ERROR_IS_OK(result)) {
3930 return result;
3933 r->description = talloc_asprintf(mem_ctx, "%s,%s,%s",
3934 r->name,
3935 info2->drivername,
3936 r->comment);
3937 W_ERROR_HAVE_NO_MEMORY(r->description);
3939 return WERR_OK;
3942 /********************************************************************
3943 * construct_printer_info2
3944 * fill a spoolss_PrinterInfo2 struct
3945 ********************************************************************/
3947 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3948 struct messaging_context *msg_ctx,
3949 const struct spoolss_PrinterInfo2 *info2,
3950 const char *servername,
3951 struct spoolss_PrinterInfo2 *r,
3952 int snum)
3954 int count;
3955 print_status_struct status;
3956 WERROR result;
3958 count = print_queue_length(msg_ctx, snum, &status);
3960 if (servername) {
3961 r->servername = talloc_strdup(mem_ctx, servername);
3962 W_ERROR_HAVE_NO_MEMORY(r->servername);
3963 } else {
3964 r->servername = NULL;
3967 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3968 if (!W_ERROR_IS_OK(result)) {
3969 return result;
3972 r->sharename = lp_servicename(mem_ctx, snum);
3973 W_ERROR_HAVE_NO_MEMORY(r->sharename);
3974 r->portname = talloc_strdup(mem_ctx, info2->portname);
3975 W_ERROR_HAVE_NO_MEMORY(r->portname);
3976 r->drivername = talloc_strdup(mem_ctx, info2->drivername);
3977 W_ERROR_HAVE_NO_MEMORY(r->drivername);
3979 if (info2->comment[0] == '\0') {
3980 r->comment = lp_comment(mem_ctx, snum);
3981 } else {
3982 r->comment = talloc_strdup(mem_ctx, info2->comment);
3984 W_ERROR_HAVE_NO_MEMORY(r->comment);
3986 r->location = talloc_strdup(mem_ctx, info2->location);
3987 if (info2->location[0] == '\0') {
3988 const char *loc = NULL;
3989 NTSTATUS nt_status;
3991 nt_status = printer_list_get_printer(mem_ctx,
3992 info2->sharename,
3993 NULL,
3994 &loc,
3995 NULL);
3996 if (NT_STATUS_IS_OK(nt_status)) {
3997 if (loc != NULL) {
3998 r->location = talloc_strdup(mem_ctx, loc);
4002 W_ERROR_HAVE_NO_MEMORY(r->location);
4004 r->sepfile = talloc_strdup(mem_ctx, info2->sepfile);
4005 W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4006 r->printprocessor = talloc_strdup(mem_ctx, info2->printprocessor);
4007 W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4008 r->datatype = talloc_strdup(mem_ctx, info2->datatype);
4009 W_ERROR_HAVE_NO_MEMORY(r->datatype);
4010 r->parameters = talloc_strdup(mem_ctx, info2->parameters);
4011 W_ERROR_HAVE_NO_MEMORY(r->parameters);
4013 r->attributes = info2->attributes;
4015 r->priority = info2->priority;
4016 r->defaultpriority = info2->defaultpriority;
4017 r->starttime = info2->starttime;
4018 r->untiltime = info2->untiltime;
4019 r->status = nt_printq_status(status.status);
4020 r->cjobs = count;
4021 r->averageppm = info2->averageppm;
4023 if (info2->devmode != NULL) {
4024 result = copy_devicemode(mem_ctx,
4025 info2->devmode,
4026 &r->devmode);
4027 if (!W_ERROR_IS_OK(result)) {
4028 return result;
4030 } else if (lp_default_devmode(snum)) {
4031 result = spoolss_create_default_devmode(mem_ctx,
4032 info2->printername,
4033 &r->devmode);
4034 if (!W_ERROR_IS_OK(result)) {
4035 return result;
4037 } else {
4038 r->devmode = NULL;
4039 DEBUG(8,("Returning NULL Devicemode!\n"));
4042 compose_devicemode_devicename(r->devmode, r->printername);
4044 r->secdesc = NULL;
4046 if (info2->secdesc != NULL) {
4047 /* don't use talloc_steal() here unless you do a deep steal of all
4048 the SEC_DESC members */
4050 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4053 return WERR_OK;
4056 /********************************************************************
4057 * construct_printer_info3
4058 * fill a spoolss_PrinterInfo3 struct
4059 ********************************************************************/
4061 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4062 const struct spoolss_PrinterInfo2 *info2,
4063 const char *servername,
4064 struct spoolss_PrinterInfo3 *r,
4065 int snum)
4067 /* These are the components of the SD we are returning. */
4069 if (info2->secdesc != NULL) {
4070 /* don't use talloc_steal() here unless you do a deep steal of all
4071 the SEC_DESC members */
4073 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4074 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
4077 return WERR_OK;
4080 /********************************************************************
4081 * construct_printer_info4
4082 * fill a spoolss_PrinterInfo4 struct
4083 ********************************************************************/
4085 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4086 const struct spoolss_PrinterInfo2 *info2,
4087 const char *servername,
4088 struct spoolss_PrinterInfo4 *r,
4089 int snum)
4091 WERROR result;
4093 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4094 if (!W_ERROR_IS_OK(result)) {
4095 return result;
4098 if (servername) {
4099 r->servername = talloc_strdup(mem_ctx, servername);
4100 W_ERROR_HAVE_NO_MEMORY(r->servername);
4101 } else {
4102 r->servername = NULL;
4105 r->attributes = info2->attributes;
4107 return WERR_OK;
4110 /********************************************************************
4111 * construct_printer_info5
4112 * fill a spoolss_PrinterInfo5 struct
4113 ********************************************************************/
4115 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4116 const struct spoolss_PrinterInfo2 *info2,
4117 const char *servername,
4118 struct spoolss_PrinterInfo5 *r,
4119 int snum)
4121 WERROR result;
4123 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4124 if (!W_ERROR_IS_OK(result)) {
4125 return result;
4128 r->portname = talloc_strdup(mem_ctx, info2->portname);
4129 W_ERROR_HAVE_NO_MEMORY(r->portname);
4131 r->attributes = info2->attributes;
4133 /* these two are not used by NT+ according to MSDN */
4134 r->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4135 r->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4137 return WERR_OK;
4140 /********************************************************************
4141 * construct_printer_info_6
4142 * fill a spoolss_PrinterInfo6 struct
4143 ********************************************************************/
4145 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4146 struct messaging_context *msg_ctx,
4147 const struct spoolss_PrinterInfo2 *info2,
4148 const char *servername,
4149 struct spoolss_PrinterInfo6 *r,
4150 int snum)
4152 print_status_struct status;
4154 print_queue_length(msg_ctx, snum, &status);
4156 r->status = nt_printq_status(status.status);
4158 return WERR_OK;
4161 /********************************************************************
4162 * construct_printer_info7
4163 * fill a spoolss_PrinterInfo7 struct
4164 ********************************************************************/
4166 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4167 struct messaging_context *msg_ctx,
4168 const char *servername,
4169 struct spoolss_PrinterInfo7 *r,
4170 int snum)
4172 const struct auth_session_info *session_info = get_session_info_system();
4173 struct GUID guid;
4175 if (is_printer_published(mem_ctx, session_info, msg_ctx,
4176 servername,
4177 lp_servicename(talloc_tos(), snum), &guid, NULL)) {
4178 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4179 r->action = DSPRINT_PUBLISH;
4180 } else {
4181 r->guid = talloc_strdup(mem_ctx, "");
4182 r->action = DSPRINT_UNPUBLISH;
4184 W_ERROR_HAVE_NO_MEMORY(r->guid);
4186 return WERR_OK;
4189 /********************************************************************
4190 * construct_printer_info8
4191 * fill a spoolss_PrinterInfo8 struct
4192 ********************************************************************/
4194 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4195 const struct spoolss_PrinterInfo2 *info2,
4196 const char *servername,
4197 struct spoolss_DeviceModeInfo *r,
4198 int snum)
4200 WERROR result;
4201 const char *printername;
4203 result = create_printername(mem_ctx, servername, info2->printername, &printername);
4204 if (!W_ERROR_IS_OK(result)) {
4205 return result;
4208 if (info2->devmode != NULL) {
4209 result = copy_devicemode(mem_ctx,
4210 info2->devmode,
4211 &r->devmode);
4212 if (!W_ERROR_IS_OK(result)) {
4213 return result;
4215 } else if (lp_default_devmode(snum)) {
4216 result = spoolss_create_default_devmode(mem_ctx,
4217 info2->printername,
4218 &r->devmode);
4219 if (!W_ERROR_IS_OK(result)) {
4220 return result;
4222 } else {
4223 r->devmode = NULL;
4224 DEBUG(8,("Returning NULL Devicemode!\n"));
4227 compose_devicemode_devicename(r->devmode, printername);
4229 return WERR_OK;
4233 /********************************************************************
4234 ********************************************************************/
4236 static bool snum_is_shared_printer(int snum)
4238 return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4241 /********************************************************************
4242 Spoolss_enumprinters.
4243 ********************************************************************/
4245 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4246 const struct auth_session_info *session_info,
4247 struct messaging_context *msg_ctx,
4248 const char *servername,
4249 uint32_t level,
4250 uint32_t flags,
4251 union spoolss_PrinterInfo **info_p,
4252 uint32_t *count_p)
4254 int snum;
4255 int n_services = lp_numservices();
4256 union spoolss_PrinterInfo *info = NULL;
4257 uint32_t count = 0;
4258 WERROR result = WERR_OK;
4259 struct dcerpc_binding_handle *b = NULL;
4260 TALLOC_CTX *tmp_ctx = NULL;
4262 tmp_ctx = talloc_new(mem_ctx);
4263 if (!tmp_ctx) {
4264 return WERR_NOMEM;
4267 *count_p = 0;
4268 *info_p = NULL;
4270 for (snum = 0; snum < n_services; snum++) {
4272 const char *printer;
4273 struct spoolss_PrinterInfo2 *info2;
4275 if (!snum_is_shared_printer(snum)) {
4276 continue;
4279 printer = lp_const_servicename(snum);
4281 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4282 printer, snum));
4284 if (b == NULL) {
4285 result = winreg_printer_binding_handle(tmp_ctx,
4286 session_info,
4287 msg_ctx,
4288 &b);
4289 if (!W_ERROR_IS_OK(result)) {
4290 goto out;
4294 result = winreg_create_printer(tmp_ctx, b,
4295 printer);
4296 if (!W_ERROR_IS_OK(result)) {
4297 goto out;
4300 info = talloc_realloc(tmp_ctx, info,
4301 union spoolss_PrinterInfo,
4302 count + 1);
4303 if (!info) {
4304 result = WERR_NOMEM;
4305 goto out;
4308 result = winreg_get_printer(tmp_ctx, b,
4309 printer, &info2);
4310 if (!W_ERROR_IS_OK(result)) {
4311 goto out;
4314 switch (level) {
4315 case 0:
4316 result = construct_printer_info0(info, session_info,
4317 msg_ctx, info2,
4318 servername,
4319 &info[count].info0, snum);
4320 break;
4321 case 1:
4322 result = construct_printer_info1(info, info2, flags,
4323 servername,
4324 &info[count].info1, snum);
4325 break;
4326 case 2:
4327 result = construct_printer_info2(info, msg_ctx, info2,
4328 servername,
4329 &info[count].info2, snum);
4330 break;
4331 case 4:
4332 result = construct_printer_info4(info, info2,
4333 servername,
4334 &info[count].info4, snum);
4335 break;
4336 case 5:
4337 result = construct_printer_info5(info, info2,
4338 servername,
4339 &info[count].info5, snum);
4340 break;
4342 default:
4343 result = WERR_UNKNOWN_LEVEL;
4344 goto out;
4347 if (!W_ERROR_IS_OK(result)) {
4348 goto out;
4351 count++;
4354 out:
4355 if (W_ERROR_IS_OK(result)) {
4356 *info_p = talloc_move(mem_ctx, &info);
4357 *count_p = count;
4360 talloc_free(tmp_ctx);
4362 return result;
4365 /********************************************************************
4366 * handle enumeration of printers at level 0
4367 ********************************************************************/
4369 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4370 const struct auth_session_info *session_info,
4371 struct messaging_context *msg_ctx,
4372 uint32_t flags,
4373 const char *servername,
4374 union spoolss_PrinterInfo **info,
4375 uint32_t *count)
4377 DEBUG(4,("enum_all_printers_info_0\n"));
4379 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4380 servername, 0, flags, info, count);
4384 /********************************************************************
4385 ********************************************************************/
4387 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4388 const struct auth_session_info *session_info,
4389 struct messaging_context *msg_ctx,
4390 const char *servername,
4391 uint32_t flags,
4392 union spoolss_PrinterInfo **info,
4393 uint32_t *count)
4395 DEBUG(4,("enum_all_printers_info_1\n"));
4397 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4398 servername, 1, flags, info, count);
4401 /********************************************************************
4402 enum_all_printers_info_1_local.
4403 *********************************************************************/
4405 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4406 const struct auth_session_info *session_info,
4407 struct messaging_context *msg_ctx,
4408 const char *servername,
4409 union spoolss_PrinterInfo **info,
4410 uint32_t *count)
4412 DEBUG(4,("enum_all_printers_info_1_local\n"));
4414 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4415 servername, PRINTER_ENUM_ICON8, info, count);
4418 /********************************************************************
4419 enum_all_printers_info_1_name.
4420 *********************************************************************/
4422 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4423 const struct auth_session_info *session_info,
4424 struct messaging_context *msg_ctx,
4425 const char *servername,
4426 union spoolss_PrinterInfo **info,
4427 uint32_t *count)
4429 const char *s = servername;
4431 DEBUG(4,("enum_all_printers_info_1_name\n"));
4433 if (servername != NULL &&
4434 (servername[0] == '\\') && (servername[1] == '\\')) {
4435 s = servername + 2;
4438 if (!is_myname_or_ipaddr(s)) {
4439 return WERR_INVALID_NAME;
4442 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4443 servername, PRINTER_ENUM_ICON8, info, count);
4446 /********************************************************************
4447 enum_all_printers_info_1_network.
4448 *********************************************************************/
4450 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4451 const struct auth_session_info *session_info,
4452 struct messaging_context *msg_ctx,
4453 const char *servername,
4454 union spoolss_PrinterInfo **info,
4455 uint32_t *count)
4457 const char *s = servername;
4459 DEBUG(4,("enum_all_printers_info_1_network\n"));
4461 /* If we respond to a enum_printers level 1 on our name with flags
4462 set to PRINTER_ENUM_REMOTE with a list of printers then these
4463 printers incorrectly appear in the APW browse list.
4464 Specifically the printers for the server appear at the workgroup
4465 level where all the other servers in the domain are
4466 listed. Windows responds to this call with a
4467 WERR_CAN_NOT_COMPLETE so we should do the same. */
4469 if (servername[0] == '\\' && servername[1] == '\\') {
4470 s = servername + 2;
4473 if (is_myname_or_ipaddr(s)) {
4474 return WERR_CAN_NOT_COMPLETE;
4477 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4478 servername, PRINTER_ENUM_NAME, info, count);
4481 /********************************************************************
4482 * api_spoolss_enumprinters
4484 * called from api_spoolss_enumprinters (see this to understand)
4485 ********************************************************************/
4487 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4488 const struct auth_session_info *session_info,
4489 struct messaging_context *msg_ctx,
4490 const char *servername,
4491 union spoolss_PrinterInfo **info,
4492 uint32_t *count)
4494 DEBUG(4,("enum_all_printers_info_2\n"));
4496 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4497 servername, 2, 0, info, count);
4500 /********************************************************************
4501 * handle enumeration of printers at level 1
4502 ********************************************************************/
4504 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4505 const struct auth_session_info *session_info,
4506 struct messaging_context *msg_ctx,
4507 uint32_t flags,
4508 const char *servername,
4509 union spoolss_PrinterInfo **info,
4510 uint32_t *count)
4512 /* Not all the flags are equals */
4514 if (flags & PRINTER_ENUM_LOCAL) {
4515 return enum_all_printers_info_1_local(mem_ctx, session_info,
4516 msg_ctx, servername, info, count);
4519 if (flags & PRINTER_ENUM_NAME) {
4520 return enum_all_printers_info_1_name(mem_ctx, session_info,
4521 msg_ctx, servername, info,
4522 count);
4525 if (flags & PRINTER_ENUM_NETWORK) {
4526 return enum_all_printers_info_1_network(mem_ctx, session_info,
4527 msg_ctx, servername, info,
4528 count);
4531 return WERR_OK; /* NT4sp5 does that */
4534 /********************************************************************
4535 * handle enumeration of printers at level 2
4536 ********************************************************************/
4538 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4539 const struct auth_session_info *session_info,
4540 struct messaging_context *msg_ctx,
4541 uint32_t flags,
4542 const char *servername,
4543 union spoolss_PrinterInfo **info,
4544 uint32_t *count)
4546 if (flags & PRINTER_ENUM_LOCAL) {
4548 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4549 servername,
4550 info, count);
4553 if (flags & PRINTER_ENUM_NAME) {
4554 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4555 return WERR_INVALID_NAME;
4558 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4559 servername,
4560 info, count);
4563 if (flags & PRINTER_ENUM_REMOTE) {
4564 return WERR_UNKNOWN_LEVEL;
4567 return WERR_OK;
4570 /********************************************************************
4571 * handle enumeration of printers at level 4
4572 ********************************************************************/
4574 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4575 const struct auth_session_info *session_info,
4576 struct messaging_context *msg_ctx,
4577 uint32_t flags,
4578 const char *servername,
4579 union spoolss_PrinterInfo **info,
4580 uint32_t *count)
4582 DEBUG(4,("enum_all_printers_info_4\n"));
4584 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4585 servername, 4, flags, info, count);
4589 /********************************************************************
4590 * handle enumeration of printers at level 5
4591 ********************************************************************/
4593 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4594 const struct auth_session_info *session_info,
4595 struct messaging_context *msg_ctx,
4596 uint32_t flags,
4597 const char *servername,
4598 union spoolss_PrinterInfo **info,
4599 uint32_t *count)
4601 DEBUG(4,("enum_all_printers_info_5\n"));
4603 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4604 servername, 5, flags, info, count);
4607 /****************************************************************
4608 _spoolss_EnumPrinters
4609 ****************************************************************/
4611 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4612 struct spoolss_EnumPrinters *r)
4614 const struct auth_session_info *session_info = get_session_info_system();
4615 WERROR result;
4617 /* that's an [in out] buffer */
4619 if (!r->in.buffer && (r->in.offered != 0)) {
4620 return WERR_INVALID_PARAM;
4623 DEBUG(4,("_spoolss_EnumPrinters\n"));
4625 *r->out.needed = 0;
4626 *r->out.count = 0;
4627 *r->out.info = NULL;
4630 * Level 1:
4631 * flags==PRINTER_ENUM_NAME
4632 * if name=="" then enumerates all printers
4633 * if name!="" then enumerate the printer
4634 * flags==PRINTER_ENUM_REMOTE
4635 * name is NULL, enumerate printers
4636 * Level 2: name!="" enumerates printers, name can't be NULL
4637 * Level 3: doesn't exist
4638 * Level 4: does a local registry lookup
4639 * Level 5: same as Level 2
4642 if (r->in.server && r->in.server[0] == '\0') {
4643 r->in.server = NULL;
4646 switch (r->in.level) {
4647 case 0:
4648 result = enumprinters_level0(p->mem_ctx, session_info,
4649 p->msg_ctx, r->in.flags,
4650 r->in.server,
4651 r->out.info, r->out.count);
4652 break;
4653 case 1:
4654 result = enumprinters_level1(p->mem_ctx, session_info,
4655 p->msg_ctx, r->in.flags,
4656 r->in.server,
4657 r->out.info, r->out.count);
4658 break;
4659 case 2:
4660 result = enumprinters_level2(p->mem_ctx, session_info,
4661 p->msg_ctx, r->in.flags,
4662 r->in.server,
4663 r->out.info, r->out.count);
4664 break;
4665 case 4:
4666 result = enumprinters_level4(p->mem_ctx, session_info,
4667 p->msg_ctx, r->in.flags,
4668 r->in.server,
4669 r->out.info, r->out.count);
4670 break;
4671 case 5:
4672 result = enumprinters_level5(p->mem_ctx, session_info,
4673 p->msg_ctx, r->in.flags,
4674 r->in.server,
4675 r->out.info, r->out.count);
4676 break;
4677 default:
4678 return WERR_UNKNOWN_LEVEL;
4681 if (!W_ERROR_IS_OK(result)) {
4682 return result;
4685 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4686 spoolss_EnumPrinters,
4687 *r->out.info, r->in.level,
4688 *r->out.count);
4689 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4690 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4692 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4695 /****************************************************************
4696 _spoolss_GetPrinter
4697 ****************************************************************/
4699 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4700 struct spoolss_GetPrinter *r)
4702 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4703 struct spoolss_PrinterInfo2 *info2 = NULL;
4704 WERROR result = WERR_OK;
4705 int snum;
4707 /* that's an [in out] buffer */
4709 if (!r->in.buffer && (r->in.offered != 0)) {
4710 return WERR_INVALID_PARAM;
4713 *r->out.needed = 0;
4715 if (Printer == NULL) {
4716 return WERR_BADFID;
4719 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4720 return WERR_BADFID;
4723 result = winreg_get_printer_internal(p->mem_ctx,
4724 get_session_info_system(),
4725 p->msg_ctx,
4726 lp_const_servicename(snum),
4727 &info2);
4728 if (!W_ERROR_IS_OK(result)) {
4729 goto out;
4732 switch (r->in.level) {
4733 case 0:
4734 result = construct_printer_info0(p->mem_ctx,
4735 get_session_info_system(),
4736 p->msg_ctx,
4737 info2,
4738 Printer->servername,
4739 &r->out.info->info0,
4740 snum);
4741 break;
4742 case 1:
4743 result = construct_printer_info1(p->mem_ctx, info2,
4744 PRINTER_ENUM_ICON8,
4745 Printer->servername,
4746 &r->out.info->info1, snum);
4747 break;
4748 case 2:
4749 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4750 Printer->servername,
4751 &r->out.info->info2, snum);
4752 break;
4753 case 3:
4754 result = construct_printer_info3(p->mem_ctx, info2,
4755 Printer->servername,
4756 &r->out.info->info3, snum);
4757 break;
4758 case 4:
4759 result = construct_printer_info4(p->mem_ctx, info2,
4760 Printer->servername,
4761 &r->out.info->info4, snum);
4762 break;
4763 case 5:
4764 result = construct_printer_info5(p->mem_ctx, info2,
4765 Printer->servername,
4766 &r->out.info->info5, snum);
4767 break;
4768 case 6:
4769 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4770 Printer->servername,
4771 &r->out.info->info6, snum);
4772 break;
4773 case 7:
4774 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4775 Printer->servername,
4776 &r->out.info->info7, snum);
4777 break;
4778 case 8:
4779 result = construct_printer_info8(p->mem_ctx, info2,
4780 Printer->servername,
4781 &r->out.info->info8, snum);
4782 break;
4783 default:
4784 result = WERR_UNKNOWN_LEVEL;
4785 break;
4787 TALLOC_FREE(info2);
4789 out:
4790 if (!W_ERROR_IS_OK(result)) {
4791 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4792 r->in.level, win_errstr(result)));
4793 TALLOC_FREE(r->out.info);
4794 return result;
4797 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4798 r->out.info, r->in.level);
4799 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4801 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4804 /********************************************************************
4805 ********************************************************************/
4807 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4808 do { \
4809 if (in && strlen(in)) { \
4810 out = talloc_strdup(mem_ctx, in); \
4811 } else { \
4812 out = talloc_strdup(mem_ctx, ""); \
4814 W_ERROR_HAVE_NO_MEMORY(out); \
4815 } while (0);
4817 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4818 do { \
4819 if (in && strlen(in)) { \
4820 out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4821 } else { \
4822 out = talloc_strdup(mem_ctx, ""); \
4824 W_ERROR_HAVE_NO_MEMORY(out); \
4825 } while (0);
4827 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4828 const char **string_array,
4829 const char ***presult,
4830 const char *cservername,
4831 const char *arch,
4832 int version)
4834 int i, num_strings = 0;
4835 const char **array = NULL;
4837 if (string_array == NULL) {
4838 return WERR_INVALID_PARAMETER;
4841 for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4842 const char *str = NULL;
4844 if (cservername == NULL || arch == NULL) {
4845 FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4846 } else {
4847 FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4850 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4851 TALLOC_FREE(array);
4852 return WERR_NOMEM;
4856 if (i > 0) {
4857 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4858 &array, &num_strings);
4861 if (presult) {
4862 *presult = array;
4865 return WERR_OK;
4868 /********************************************************************
4869 * fill a spoolss_DriverInfo1 struct
4870 ********************************************************************/
4872 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4873 struct spoolss_DriverInfo1 *r,
4874 const struct spoolss_DriverInfo8 *driver,
4875 const char *servername)
4877 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4878 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4880 return WERR_OK;
4883 /********************************************************************
4884 * fill a spoolss_DriverInfo2 struct
4885 ********************************************************************/
4887 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4888 struct spoolss_DriverInfo2 *r,
4889 const struct spoolss_DriverInfo8 *driver,
4890 const char *servername)
4893 const char *cservername = canon_servername(servername);
4895 r->version = driver->version;
4897 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4898 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4899 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4900 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4902 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4903 driver->architecture,
4904 driver->version,
4905 driver->driver_path,
4906 r->driver_path);
4908 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4909 driver->architecture,
4910 driver->version,
4911 driver->data_file,
4912 r->data_file);
4914 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4915 driver->architecture,
4916 driver->version,
4917 driver->config_file,
4918 r->config_file);
4920 return WERR_OK;
4923 /********************************************************************
4924 * fill a spoolss_DriverInfo3 struct
4925 ********************************************************************/
4927 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4928 struct spoolss_DriverInfo3 *r,
4929 const struct spoolss_DriverInfo8 *driver,
4930 const char *servername)
4932 const char *cservername = canon_servername(servername);
4934 r->version = driver->version;
4936 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4937 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4938 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4939 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4941 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4942 driver->architecture,
4943 driver->version,
4944 driver->driver_path,
4945 r->driver_path);
4947 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4948 driver->architecture,
4949 driver->version,
4950 driver->data_file,
4951 r->data_file);
4953 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4954 driver->architecture,
4955 driver->version,
4956 driver->config_file,
4957 r->config_file);
4959 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4960 driver->architecture,
4961 driver->version,
4962 driver->help_file,
4963 r->help_file);
4965 FILL_DRIVER_STRING(mem_ctx,
4966 driver->monitor_name,
4967 r->monitor_name);
4969 FILL_DRIVER_STRING(mem_ctx,
4970 driver->default_datatype,
4971 r->default_datatype);
4973 return string_array_from_driver_info(mem_ctx,
4974 driver->dependent_files,
4975 &r->dependent_files,
4976 cservername,
4977 driver->architecture,
4978 driver->version);
4981 /********************************************************************
4982 * fill a spoolss_DriverInfo4 struct
4983 ********************************************************************/
4985 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4986 struct spoolss_DriverInfo4 *r,
4987 const struct spoolss_DriverInfo8 *driver,
4988 const char *servername)
4990 const char *cservername = canon_servername(servername);
4991 WERROR result;
4993 r->version = driver->version;
4995 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4996 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4997 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4998 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5000 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5001 driver->architecture,
5002 driver->version,
5003 driver->driver_path,
5004 r->driver_path);
5006 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5007 driver->architecture,
5008 driver->version,
5009 driver->data_file,
5010 r->data_file);
5012 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5013 driver->architecture,
5014 driver->version,
5015 driver->config_file,
5016 r->config_file);
5018 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5019 driver->architecture,
5020 driver->version,
5021 driver->help_file,
5022 r->help_file);
5024 result = string_array_from_driver_info(mem_ctx,
5025 driver->dependent_files,
5026 &r->dependent_files,
5027 cservername,
5028 driver->architecture,
5029 driver->version);
5030 if (!W_ERROR_IS_OK(result)) {
5031 return result;
5034 FILL_DRIVER_STRING(mem_ctx,
5035 driver->monitor_name,
5036 r->monitor_name);
5038 FILL_DRIVER_STRING(mem_ctx,
5039 driver->default_datatype,
5040 r->default_datatype);
5043 result = string_array_from_driver_info(mem_ctx,
5044 driver->previous_names,
5045 &r->previous_names,
5046 NULL, NULL, 0);
5048 return result;
5051 /********************************************************************
5052 * fill a spoolss_DriverInfo5 struct
5053 ********************************************************************/
5055 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5056 struct spoolss_DriverInfo5 *r,
5057 const struct spoolss_DriverInfo8 *driver,
5058 const char *servername)
5060 const char *cservername = canon_servername(servername);
5062 r->version = driver->version;
5064 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5065 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5066 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5067 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5069 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5070 driver->architecture,
5071 driver->version,
5072 driver->driver_path,
5073 r->driver_path);
5075 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5076 driver->architecture,
5077 driver->version,
5078 driver->data_file,
5079 r->data_file);
5081 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5082 driver->architecture,
5083 driver->version,
5084 driver->config_file,
5085 r->config_file);
5087 r->driver_attributes = 0;
5088 r->config_version = 0;
5089 r->driver_version = 0;
5091 return WERR_OK;
5093 /********************************************************************
5094 * fill a spoolss_DriverInfo6 struct
5095 ********************************************************************/
5097 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5098 struct spoolss_DriverInfo6 *r,
5099 const struct spoolss_DriverInfo8 *driver,
5100 const char *servername)
5102 const char *cservername = canon_servername(servername);
5103 WERROR result;
5105 r->version = driver->version;
5107 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5108 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5109 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5110 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5112 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5113 driver->architecture,
5114 driver->version,
5115 driver->driver_path,
5116 r->driver_path);
5118 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5119 driver->architecture,
5120 driver->version,
5121 driver->data_file,
5122 r->data_file);
5124 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5125 driver->architecture,
5126 driver->version,
5127 driver->config_file,
5128 r->config_file);
5130 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5131 driver->architecture,
5132 driver->version,
5133 driver->help_file,
5134 r->help_file);
5136 FILL_DRIVER_STRING(mem_ctx,
5137 driver->monitor_name,
5138 r->monitor_name);
5140 FILL_DRIVER_STRING(mem_ctx,
5141 driver->default_datatype,
5142 r->default_datatype);
5144 result = string_array_from_driver_info(mem_ctx,
5145 driver->dependent_files,
5146 &r->dependent_files,
5147 cservername,
5148 driver->architecture,
5149 driver->version);
5150 if (!W_ERROR_IS_OK(result)) {
5151 return result;
5154 result = string_array_from_driver_info(mem_ctx,
5155 driver->previous_names,
5156 &r->previous_names,
5157 NULL, NULL, 0);
5158 if (!W_ERROR_IS_OK(result)) {
5159 return result;
5162 r->driver_date = driver->driver_date;
5163 r->driver_version = driver->driver_version;
5165 FILL_DRIVER_STRING(mem_ctx,
5166 driver->manufacturer_name,
5167 r->manufacturer_name);
5168 FILL_DRIVER_STRING(mem_ctx,
5169 driver->manufacturer_url,
5170 r->manufacturer_url);
5171 FILL_DRIVER_STRING(mem_ctx,
5172 driver->hardware_id,
5173 r->hardware_id);
5174 FILL_DRIVER_STRING(mem_ctx,
5175 driver->provider,
5176 r->provider);
5178 return WERR_OK;
5181 /********************************************************************
5182 * fill a spoolss_DriverInfo8 struct
5183 ********************************************************************/
5185 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5186 struct spoolss_DriverInfo8 *r,
5187 const struct spoolss_DriverInfo8 *driver,
5188 const char *servername)
5190 const char *cservername = canon_servername(servername);
5191 WERROR result;
5193 r->version = driver->version;
5195 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5196 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5197 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5198 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5200 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5201 driver->architecture,
5202 driver->version,
5203 driver->driver_path,
5204 r->driver_path);
5206 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5207 driver->architecture,
5208 driver->version,
5209 driver->data_file,
5210 r->data_file);
5212 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5213 driver->architecture,
5214 driver->version,
5215 driver->config_file,
5216 r->config_file);
5218 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5219 driver->architecture,
5220 driver->version,
5221 driver->help_file,
5222 r->help_file);
5224 FILL_DRIVER_STRING(mem_ctx,
5225 driver->monitor_name,
5226 r->monitor_name);
5228 FILL_DRIVER_STRING(mem_ctx,
5229 driver->default_datatype,
5230 r->default_datatype);
5232 result = string_array_from_driver_info(mem_ctx,
5233 driver->dependent_files,
5234 &r->dependent_files,
5235 cservername,
5236 driver->architecture,
5237 driver->version);
5238 if (!W_ERROR_IS_OK(result)) {
5239 return result;
5242 result = string_array_from_driver_info(mem_ctx,
5243 driver->previous_names,
5244 &r->previous_names,
5245 NULL, NULL, 0);
5246 if (!W_ERROR_IS_OK(result)) {
5247 return result;
5250 r->driver_date = driver->driver_date;
5251 r->driver_version = driver->driver_version;
5253 FILL_DRIVER_STRING(mem_ctx,
5254 driver->manufacturer_name,
5255 r->manufacturer_name);
5256 FILL_DRIVER_STRING(mem_ctx,
5257 driver->manufacturer_url,
5258 r->manufacturer_url);
5259 FILL_DRIVER_STRING(mem_ctx,
5260 driver->hardware_id,
5261 r->hardware_id);
5262 FILL_DRIVER_STRING(mem_ctx,
5263 driver->provider,
5264 r->provider);
5266 FILL_DRIVER_STRING(mem_ctx,
5267 driver->print_processor,
5268 r->print_processor);
5269 FILL_DRIVER_STRING(mem_ctx,
5270 driver->vendor_setup,
5271 r->vendor_setup);
5273 result = string_array_from_driver_info(mem_ctx,
5274 driver->color_profiles,
5275 &r->color_profiles,
5276 NULL, NULL, 0);
5277 if (!W_ERROR_IS_OK(result)) {
5278 return result;
5281 FILL_DRIVER_STRING(mem_ctx,
5282 driver->inf_path,
5283 r->inf_path);
5285 r->printer_driver_attributes = driver->printer_driver_attributes;
5287 result = string_array_from_driver_info(mem_ctx,
5288 driver->core_driver_dependencies,
5289 &r->core_driver_dependencies,
5290 NULL, NULL, 0);
5291 if (!W_ERROR_IS_OK(result)) {
5292 return result;
5295 r->min_inbox_driver_ver_date = driver->min_inbox_driver_ver_date;
5296 r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5298 return WERR_OK;
5301 #if 0 /* disabled until marshalling issues are resolved - gd */
5302 /********************************************************************
5303 ********************************************************************/
5305 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5306 struct spoolss_DriverFileInfo *r,
5307 const char *cservername,
5308 const char *file_name,
5309 enum spoolss_DriverFileType file_type,
5310 uint32_t file_version)
5312 r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
5313 cservername, file_name);
5314 W_ERROR_HAVE_NO_MEMORY(r->file_name);
5315 r->file_type = file_type;
5316 r->file_version = file_version;
5318 return WERR_OK;
5321 /********************************************************************
5322 ********************************************************************/
5324 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5325 const struct spoolss_DriverInfo8 *driver,
5326 const char *cservername,
5327 struct spoolss_DriverFileInfo **info_p,
5328 uint32_t *count_p)
5330 struct spoolss_DriverFileInfo *info = NULL;
5331 uint32_t count = 0;
5332 WERROR result;
5333 uint32_t i;
5335 *info_p = NULL;
5336 *count_p = 0;
5338 if (strlen(driver->driver_path)) {
5339 info = talloc_realloc(mem_ctx, info,
5340 struct spoolss_DriverFileInfo,
5341 count + 1);
5342 W_ERROR_HAVE_NO_MEMORY(info);
5343 result = fill_spoolss_DriverFileInfo(info,
5344 &info[count],
5345 cservername,
5346 driver->driver_path,
5347 SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5349 W_ERROR_NOT_OK_RETURN(result);
5350 count++;
5353 if (strlen(driver->config_file)) {
5354 info = talloc_realloc(mem_ctx, info,
5355 struct spoolss_DriverFileInfo,
5356 count + 1);
5357 W_ERROR_HAVE_NO_MEMORY(info);
5358 result = fill_spoolss_DriverFileInfo(info,
5359 &info[count],
5360 cservername,
5361 driver->config_file,
5362 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5364 W_ERROR_NOT_OK_RETURN(result);
5365 count++;
5368 if (strlen(driver->data_file)) {
5369 info = talloc_realloc(mem_ctx, info,
5370 struct spoolss_DriverFileInfo,
5371 count + 1);
5372 W_ERROR_HAVE_NO_MEMORY(info);
5373 result = fill_spoolss_DriverFileInfo(info,
5374 &info[count],
5375 cservername,
5376 driver->data_file,
5377 SPOOLSS_DRIVER_FILE_TYPE_DATA,
5379 W_ERROR_NOT_OK_RETURN(result);
5380 count++;
5383 if (strlen(driver->help_file)) {
5384 info = talloc_realloc(mem_ctx, info,
5385 struct spoolss_DriverFileInfo,
5386 count + 1);
5387 W_ERROR_HAVE_NO_MEMORY(info);
5388 result = fill_spoolss_DriverFileInfo(info,
5389 &info[count],
5390 cservername,
5391 driver->help_file,
5392 SPOOLSS_DRIVER_FILE_TYPE_HELP,
5394 W_ERROR_NOT_OK_RETURN(result);
5395 count++;
5398 for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5399 info = talloc_realloc(mem_ctx, info,
5400 struct spoolss_DriverFileInfo,
5401 count + 1);
5402 W_ERROR_HAVE_NO_MEMORY(info);
5403 result = fill_spoolss_DriverFileInfo(info,
5404 &info[count],
5405 cservername,
5406 driver->dependent_files[i],
5407 SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5409 W_ERROR_NOT_OK_RETURN(result);
5410 count++;
5413 *info_p = info;
5414 *count_p = count;
5416 return WERR_OK;
5419 /********************************************************************
5420 * fill a spoolss_DriverInfo101 struct
5421 ********************************************************************/
5423 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5424 struct spoolss_DriverInfo101 *r,
5425 const struct spoolss_DriverInfo8 *driver,
5426 const char *servername)
5428 const char *cservername = canon_servername(servername);
5429 WERROR result;
5431 r->version = driver->version;
5433 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5434 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5435 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5436 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5438 result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5439 cservername,
5440 &r->file_info,
5441 &r->file_count);
5442 if (!W_ERROR_IS_OK(result)) {
5443 return result;
5446 FILL_DRIVER_STRING(mem_ctx,
5447 driver->monitor_name,
5448 r->monitor_name);
5450 FILL_DRIVER_STRING(mem_ctx,
5451 driver->default_datatype,
5452 r->default_datatype);
5454 result = string_array_from_driver_info(mem_ctx,
5455 driver->previous_names,
5456 &r->previous_names,
5457 NULL, NULL, 0);
5458 if (!W_ERROR_IS_OK(result)) {
5459 return result;
5462 r->driver_date = driver->driver_date;
5463 r->driver_version = driver->driver_version;
5465 FILL_DRIVER_STRING(mem_ctx,
5466 driver->manufacturer_name,
5467 r->manufacturer_name);
5468 FILL_DRIVER_STRING(mem_ctx,
5469 driver->manufacturer_url,
5470 r->manufacturer_url);
5471 FILL_DRIVER_STRING(mem_ctx,
5472 driver->hardware_id,
5473 r->hardware_id);
5474 FILL_DRIVER_STRING(mem_ctx,
5475 driver->provider,
5476 r->provider);
5478 return WERR_OK;
5480 #endif
5481 /********************************************************************
5482 ********************************************************************/
5484 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5485 const struct auth_session_info *session_info,
5486 struct messaging_context *msg_ctx,
5487 uint32_t level,
5488 union spoolss_DriverInfo *r,
5489 int snum,
5490 const char *servername,
5491 const char *architecture,
5492 uint32_t version)
5494 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5495 struct spoolss_DriverInfo8 *driver;
5496 WERROR result;
5497 struct dcerpc_binding_handle *b;
5498 TALLOC_CTX *tmp_ctx = NULL;
5500 if (level == 101) {
5501 return WERR_UNKNOWN_LEVEL;
5504 tmp_ctx = talloc_new(mem_ctx);
5505 if (!tmp_ctx) {
5506 return WERR_NOMEM;
5509 result = winreg_printer_binding_handle(tmp_ctx,
5510 session_info,
5511 msg_ctx,
5512 &b);
5513 if (!W_ERROR_IS_OK(result)) {
5514 goto done;
5517 result = winreg_get_printer(tmp_ctx, b,
5518 lp_const_servicename(snum),
5519 &pinfo2);
5521 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5522 win_errstr(result)));
5524 if (!W_ERROR_IS_OK(result)) {
5525 result = WERR_INVALID_PRINTER_NAME;
5526 goto done;
5529 result = winreg_get_driver(tmp_ctx, b,
5530 architecture,
5531 pinfo2->drivername, version, &driver);
5533 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5534 win_errstr(result)));
5536 if (!W_ERROR_IS_OK(result)) {
5538 * Is this a W2k client ?
5541 if (version < 3) {
5542 result = WERR_UNKNOWN_PRINTER_DRIVER;
5543 goto done;
5546 /* Yes - try again with a WinNT driver. */
5547 version = 2;
5548 result = winreg_get_driver(tmp_ctx, b,
5549 architecture,
5550 pinfo2->drivername,
5551 version, &driver);
5552 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5553 win_errstr(result)));
5554 if (!W_ERROR_IS_OK(result)) {
5555 result = WERR_UNKNOWN_PRINTER_DRIVER;
5556 goto done;
5560 /* these are allocated on mem_ctx and not tmp_ctx because they are
5561 * the 'return value' and need to utlive this call */
5562 switch (level) {
5563 case 1:
5564 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5565 break;
5566 case 2:
5567 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5568 break;
5569 case 3:
5570 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5571 break;
5572 case 4:
5573 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5574 break;
5575 case 5:
5576 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5577 break;
5578 case 6:
5579 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5580 break;
5581 case 8:
5582 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5583 break;
5584 #if 0 /* disabled until marshalling issues are resolved - gd */
5585 case 101:
5586 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5587 break;
5588 #endif
5589 default:
5590 result = WERR_UNKNOWN_LEVEL;
5591 break;
5594 done:
5595 talloc_free(tmp_ctx);
5596 return result;
5599 /****************************************************************
5600 _spoolss_GetPrinterDriver2
5601 ****************************************************************/
5603 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5604 struct spoolss_GetPrinterDriver2 *r)
5606 struct printer_handle *printer;
5607 WERROR result;
5609 int snum;
5611 /* that's an [in out] buffer */
5613 if (!r->in.buffer && (r->in.offered != 0)) {
5614 return WERR_INVALID_PARAM;
5617 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5619 if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5620 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5621 return WERR_INVALID_PRINTER_NAME;
5624 *r->out.needed = 0;
5625 *r->out.server_major_version = 0;
5626 *r->out.server_minor_version = 0;
5628 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5629 return WERR_BADFID;
5632 result = construct_printer_driver_info_level(p->mem_ctx,
5633 get_session_info_system(),
5634 p->msg_ctx,
5635 r->in.level, r->out.info,
5636 snum, printer->servername,
5637 r->in.architecture,
5638 r->in.client_major_version);
5639 if (!W_ERROR_IS_OK(result)) {
5640 TALLOC_FREE(r->out.info);
5641 return result;
5644 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5645 r->out.info, r->in.level);
5646 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5648 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5652 /****************************************************************
5653 _spoolss_StartPagePrinter
5654 ****************************************************************/
5656 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5657 struct spoolss_StartPagePrinter *r)
5659 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5661 if (!Printer) {
5662 DEBUG(3,("_spoolss_StartPagePrinter: "
5663 "Error in startpageprinter printer handle\n"));
5664 return WERR_BADFID;
5667 Printer->page_started = true;
5668 return WERR_OK;
5671 /****************************************************************
5672 _spoolss_EndPagePrinter
5673 ****************************************************************/
5675 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5676 struct spoolss_EndPagePrinter *r)
5678 int snum;
5680 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5682 if (!Printer) {
5683 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5684 OUR_HANDLE(r->in.handle)));
5685 return WERR_BADFID;
5688 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5689 return WERR_BADFID;
5691 Printer->page_started = false;
5692 print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5694 return WERR_OK;
5697 /****************************************************************
5698 _spoolss_StartDocPrinter
5699 ****************************************************************/
5701 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5702 struct spoolss_StartDocPrinter *r)
5704 struct spoolss_DocumentInfo1 *info_1;
5705 int snum;
5706 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5707 WERROR werr;
5708 char *rhost;
5709 int rc;
5711 if (!Printer) {
5712 DEBUG(2,("_spoolss_StartDocPrinter: "
5713 "Invalid handle (%s:%u:%u)\n",
5714 OUR_HANDLE(r->in.handle)));
5715 return WERR_BADFID;
5718 if (Printer->jobid) {
5719 DEBUG(2, ("_spoolss_StartDocPrinter: "
5720 "StartDocPrinter called twice! "
5721 "(existing jobid = %d)\n", Printer->jobid));
5722 return WERR_INVALID_HANDLE;
5725 if (r->in.level != 1) {
5726 return WERR_UNKNOWN_LEVEL;
5729 info_1 = r->in.info.info1;
5732 * a nice thing with NT is it doesn't listen to what you tell it.
5733 * when asked to send _only_ RAW datas, it tries to send datas
5734 * in EMF format.
5736 * So I add checks like in NT Server ...
5739 if (info_1->datatype) {
5740 if (strcmp(info_1->datatype, "RAW") != 0) {
5741 *r->out.job_id = 0;
5742 return WERR_INVALID_DATATYPE;
5746 /* get the share number of the printer */
5747 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5748 return WERR_BADFID;
5751 rc = get_remote_hostname(p->remote_address,
5752 &rhost,
5753 p->mem_ctx);
5754 if (rc < 0) {
5755 return WERR_NOMEM;
5757 if (strequal(rhost,"UNKNOWN")) {
5758 rhost = tsocket_address_inet_addr_string(p->remote_address,
5759 p->mem_ctx);
5760 if (rhost == NULL) {
5761 return WERR_NOMEM;
5765 werr = print_job_start(p->session_info,
5766 p->msg_ctx,
5767 rhost,
5768 snum,
5769 info_1->document_name,
5770 info_1->output_file,
5771 Printer->devmode,
5772 &Printer->jobid);
5774 /* An error occured in print_job_start() so return an appropriate
5775 NT error code. */
5777 if (!W_ERROR_IS_OK(werr)) {
5778 return werr;
5781 Printer->document_started = true;
5782 *r->out.job_id = Printer->jobid;
5784 return WERR_OK;
5787 /****************************************************************
5788 _spoolss_EndDocPrinter
5789 ****************************************************************/
5791 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5792 struct spoolss_EndDocPrinter *r)
5794 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5795 NTSTATUS status;
5796 int snum;
5798 if (!Printer) {
5799 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5800 OUR_HANDLE(r->in.handle)));
5801 return WERR_BADFID;
5804 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5805 return WERR_BADFID;
5808 Printer->document_started = false;
5809 status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5810 if (!NT_STATUS_IS_OK(status)) {
5811 DEBUG(2, ("_spoolss_EndDocPrinter: "
5812 "print_job_end failed [%s]\n",
5813 nt_errstr(status)));
5816 Printer->jobid = 0;
5817 return ntstatus_to_werror(status);
5820 /****************************************************************
5821 _spoolss_WritePrinter
5822 ****************************************************************/
5824 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5825 struct spoolss_WritePrinter *r)
5827 ssize_t buffer_written;
5828 int snum;
5829 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5831 if (!Printer) {
5832 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5833 OUR_HANDLE(r->in.handle)));
5834 *r->out.num_written = r->in._data_size;
5835 return WERR_BADFID;
5838 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5839 return WERR_BADFID;
5841 /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5842 buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5843 snum, Printer->jobid,
5844 (const char *)r->in.data.data,
5845 (size_t)r->in._data_size);
5846 if (buffer_written == (ssize_t)-1) {
5847 *r->out.num_written = 0;
5848 if (errno == ENOSPC)
5849 return WERR_NO_SPOOL_SPACE;
5850 else
5851 return WERR_ACCESS_DENIED;
5854 *r->out.num_written = r->in._data_size;
5856 return WERR_OK;
5859 /********************************************************************
5860 * api_spoolss_getprinter
5861 * called from the spoolss dispatcher
5863 ********************************************************************/
5865 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5866 struct pipes_struct *p)
5868 const struct auth_session_info *session_info = p->session_info;
5869 int snum;
5870 WERROR errcode = WERR_BADFUNC;
5871 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5873 if (!Printer) {
5874 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5875 OUR_HANDLE(handle)));
5876 return WERR_BADFID;
5879 if (!get_printer_snum(p, handle, &snum, NULL))
5880 return WERR_BADFID;
5882 switch (command) {
5883 case SPOOLSS_PRINTER_CONTROL_PAUSE:
5884 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
5885 break;
5886 case SPOOLSS_PRINTER_CONTROL_RESUME:
5887 case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5888 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
5889 break;
5890 case SPOOLSS_PRINTER_CONTROL_PURGE:
5891 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
5892 break;
5893 default:
5894 return WERR_UNKNOWN_LEVEL;
5897 return errcode;
5901 /****************************************************************
5902 _spoolss_AbortPrinter
5903 * From MSDN: "Deletes printer's spool file if printer is configured
5904 * for spooling"
5905 ****************************************************************/
5907 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
5908 struct spoolss_AbortPrinter *r)
5910 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5911 int snum;
5912 WERROR errcode = WERR_OK;
5914 if (!Printer) {
5915 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5916 OUR_HANDLE(r->in.handle)));
5917 return WERR_BADFID;
5920 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5921 return WERR_BADFID;
5923 if (!Printer->document_started) {
5924 return WERR_SPL_NO_STARTDOC;
5927 errcode = print_job_delete(p->session_info,
5928 p->msg_ctx,
5929 snum,
5930 Printer->jobid);
5932 return errcode;
5935 /********************************************************************
5936 * called by spoolss_api_setprinter
5937 * when updating a printer description
5938 ********************************************************************/
5940 static WERROR update_printer_sec(struct policy_handle *handle,
5941 struct pipes_struct *p,
5942 struct sec_desc_buf *secdesc_ctr)
5944 struct spoolss_security_descriptor *new_secdesc = NULL;
5945 struct spoolss_security_descriptor *old_secdesc = NULL;
5946 const char *printer;
5947 WERROR result;
5948 int snum;
5949 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5950 struct dcerpc_binding_handle *b;
5951 TALLOC_CTX *tmp_ctx = NULL;
5953 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5954 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5955 OUR_HANDLE(handle)));
5957 result = WERR_BADFID;
5958 goto done;
5961 if (secdesc_ctr == NULL) {
5962 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5963 result = WERR_INVALID_PARAM;
5964 goto done;
5966 printer = lp_const_servicename(snum);
5968 /* Check the user has permissions to change the security
5969 descriptor. By experimentation with two NT machines, the user
5970 requires Full Access to the printer to change security
5971 information. */
5973 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5974 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5975 result = WERR_ACCESS_DENIED;
5976 goto done;
5979 tmp_ctx = talloc_new(p->mem_ctx);
5980 if (!tmp_ctx) {
5981 return WERR_NOMEM;
5984 result = winreg_printer_binding_handle(tmp_ctx,
5985 get_session_info_system(),
5986 p->msg_ctx,
5987 &b);
5988 if (!W_ERROR_IS_OK(result)) {
5989 goto done;
5992 /* NT seems to like setting the security descriptor even though
5993 nothing may have actually changed. */
5994 result = winreg_get_printer_secdesc(tmp_ctx, b,
5995 printer,
5996 &old_secdesc);
5997 if (!W_ERROR_IS_OK(result)) {
5998 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
5999 result = WERR_BADFID;
6000 goto done;
6003 if (DEBUGLEVEL >= 10) {
6004 struct security_acl *the_acl;
6005 int i;
6007 the_acl = old_secdesc->dacl;
6008 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6009 printer, the_acl->num_aces));
6011 for (i = 0; i < the_acl->num_aces; i++) {
6012 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6013 &the_acl->aces[i].trustee),
6014 the_acl->aces[i].access_mask));
6017 the_acl = secdesc_ctr->sd->dacl;
6019 if (the_acl) {
6020 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6021 printer, the_acl->num_aces));
6023 for (i = 0; i < the_acl->num_aces; i++) {
6024 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6025 &the_acl->aces[i].trustee),
6026 the_acl->aces[i].access_mask));
6028 } else {
6029 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6033 new_secdesc = sec_desc_merge(tmp_ctx, secdesc_ctr->sd, old_secdesc);
6034 if (new_secdesc == NULL) {
6035 result = WERR_NOMEM;
6036 goto done;
6039 if (security_descriptor_equal(new_secdesc, old_secdesc)) {
6040 result = WERR_OK;
6041 goto done;
6044 result = winreg_set_printer_secdesc(tmp_ctx, b,
6045 printer,
6046 new_secdesc);
6048 done:
6049 talloc_free(tmp_ctx);
6050 return result;
6053 /********************************************************************
6054 Canonicalize printer info from a client
6055 ********************************************************************/
6057 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
6058 struct spoolss_SetPrinterInfo2 *info2,
6059 int snum)
6061 fstring printername;
6062 const char *p;
6064 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6065 "portname=%s drivername=%s comment=%s location=%s\n",
6066 info2->servername, info2->printername, info2->sharename,
6067 info2->portname, info2->drivername, info2->comment,
6068 info2->location));
6070 /* we force some elements to "correct" values */
6071 info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
6072 if (info2->servername == NULL) {
6073 return false;
6075 info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6076 if (info2->sharename == NULL) {
6077 return false;
6080 /* check to see if we allow printername != sharename */
6081 if (lp_force_printername(snum)) {
6082 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6083 lp_netbios_name(), info2->sharename);
6084 } else {
6085 /* make sure printername is in \\server\printername format */
6086 fstrcpy(printername, info2->printername);
6087 p = printername;
6088 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6089 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6090 p++;
6093 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6094 lp_netbios_name(), p);
6096 if (info2->printername == NULL) {
6097 return false;
6100 info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6101 info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6103 return true;
6106 /****************************************************************************
6107 ****************************************************************************/
6109 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6111 char *cmd = lp_addport_cmd(talloc_tos());
6112 char *command = NULL;
6113 int ret;
6114 bool is_print_op = false;
6116 if ( !*cmd ) {
6117 return WERR_ACCESS_DENIED;
6120 command = talloc_asprintf(ctx,
6121 "%s \"%s\" \"%s\"", cmd, portname, uri );
6122 if (!command) {
6123 return WERR_NOMEM;
6126 if ( token )
6127 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6129 DEBUG(10,("Running [%s]\n", command));
6131 /********* BEGIN SePrintOperatorPrivilege **********/
6133 if ( is_print_op )
6134 become_root();
6136 ret = smbrun(command, NULL);
6138 if ( is_print_op )
6139 unbecome_root();
6141 /********* END SePrintOperatorPrivilege **********/
6143 DEBUGADD(10,("returned [%d]\n", ret));
6145 TALLOC_FREE(command);
6147 if ( ret != 0 ) {
6148 return WERR_ACCESS_DENIED;
6151 return WERR_OK;
6154 /****************************************************************************
6155 ****************************************************************************/
6157 static bool spoolss_conn_snum_used(struct smbd_server_connection *sconn,
6158 int snum)
6161 * As we do not know if we are embedded in the file server process
6162 * or not, we have to pretend that all shares are in use.
6164 return true;
6167 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6168 struct spoolss_SetPrinterInfo2 *info2,
6169 const char *remote_machine,
6170 struct messaging_context *msg_ctx)
6172 char *cmd = lp_addprinter_cmd(talloc_tos());
6173 char **qlines;
6174 char *command = NULL;
6175 int numlines;
6176 int ret;
6177 int fd;
6178 bool is_print_op = false;
6180 if (!remote_machine) {
6181 return false;
6184 command = talloc_asprintf(ctx,
6185 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6186 cmd, info2->printername, info2->sharename,
6187 info2->portname, info2->drivername,
6188 info2->location, info2->comment, remote_machine);
6189 if (!command) {
6190 return false;
6193 if ( token )
6194 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6196 DEBUG(10,("Running [%s]\n", command));
6198 /********* BEGIN SePrintOperatorPrivilege **********/
6200 if ( is_print_op )
6201 become_root();
6203 if ( (ret = smbrun(command, &fd)) == 0 ) {
6204 /* Tell everyone we updated smb.conf. */
6205 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6208 if ( is_print_op )
6209 unbecome_root();
6211 /********* END SePrintOperatorPrivilege **********/
6213 DEBUGADD(10,("returned [%d]\n", ret));
6215 TALLOC_FREE(command);
6217 if ( ret != 0 ) {
6218 if (fd != -1)
6219 close(fd);
6220 return false;
6223 /* reload our services immediately */
6224 become_root();
6225 reload_services(NULL, spoolss_conn_snum_used, false);
6226 unbecome_root();
6228 numlines = 0;
6229 /* Get lines and convert them back to dos-codepage */
6230 qlines = fd_lines_load(fd, &numlines, 0, NULL);
6231 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6232 close(fd);
6234 /* Set the portname to what the script says the portname should be. */
6235 /* but don't require anything to be return from the script exit a good error code */
6237 if (numlines) {
6238 /* Set the portname to what the script says the portname should be. */
6239 info2->portname = talloc_strdup(ctx, qlines[0]);
6240 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6243 TALLOC_FREE(qlines);
6244 return true;
6247 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6248 const struct auth_session_info *session_info,
6249 struct messaging_context *msg_ctx,
6250 int snum,
6251 struct spoolss_SetPrinterInfo2 *printer,
6252 struct spoolss_PrinterInfo2 *old_printer)
6254 bool force_update = (old_printer == NULL);
6255 const char *dnsdomname;
6256 const char *longname;
6257 const char *uncname;
6258 const char *spooling;
6259 DATA_BLOB buffer;
6260 WERROR result = WERR_OK;
6261 struct dcerpc_binding_handle *b;
6262 TALLOC_CTX *tmp_ctx;
6263 bool ok;
6265 tmp_ctx = talloc_new(mem_ctx);
6266 if (!tmp_ctx) {
6267 return WERR_NOMEM;
6270 result = winreg_printer_binding_handle(tmp_ctx,
6271 session_info,
6272 msg_ctx,
6273 &b);
6274 if (!W_ERROR_IS_OK(result)) {
6275 goto done;
6278 if (printer->drivername != NULL &&
6279 (force_update ||
6280 !strequal(printer->drivername, old_printer->drivername))) {
6281 ok = push_reg_sz(tmp_ctx, &buffer, printer->drivername);
6282 if (!ok) {
6283 DEBUG(0, ("%s data corrupted\n", SPOOL_REG_DRIVERNAME));
6284 result = WERR_INVALID_DATA;
6285 goto done;
6287 result = winreg_set_printer_dataex(tmp_ctx, b,
6288 printer->sharename,
6289 SPOOL_DSSPOOLER_KEY,
6290 SPOOL_REG_DRIVERNAME,
6291 REG_SZ,
6292 buffer.data,
6293 buffer.length);
6294 if (!W_ERROR_IS_OK(result)) {
6295 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DRIVERNAME));
6296 goto done;
6299 if (!force_update) {
6300 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6301 printer->drivername));
6303 notify_printer_driver(server_event_context(), msg_ctx,
6304 snum, printer->drivername ?
6305 printer->drivername : "");
6309 if (printer->comment != NULL &&
6310 (force_update ||
6311 !strequal(printer->comment, old_printer->comment))) {
6312 ok = push_reg_sz(tmp_ctx, &buffer, printer->comment);
6313 if (!ok) {
6314 DEBUG(0, ("comment data corrupted\n"));
6315 result = WERR_INVALID_DATA;
6316 goto done;
6318 result = winreg_set_printer_dataex(tmp_ctx, b,
6319 printer->sharename,
6320 SPOOL_DSSPOOLER_KEY,
6321 SPOOL_REG_DESCRIPTION,
6322 REG_SZ,
6323 buffer.data,
6324 buffer.length);
6325 if (!W_ERROR_IS_OK(result)) {
6326 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DESCRIPTION));
6327 goto done;
6330 if (!force_update) {
6331 notify_printer_comment(server_event_context(), msg_ctx,
6332 snum, printer->comment ?
6333 printer->comment : "");
6337 if (printer->sharename != NULL &&
6338 (force_update ||
6339 !strequal(printer->sharename, old_printer->sharename))) {
6340 ok = push_reg_sz(tmp_ctx, &buffer, printer->sharename);
6341 if (!ok) {
6342 DEBUG(0, ("sharename data corrupted\n"));
6343 result = WERR_INVALID_DATA;
6344 goto done;
6346 result = winreg_set_printer_dataex(tmp_ctx, b,
6347 printer->sharename,
6348 SPOOL_DSSPOOLER_KEY,
6349 SPOOL_REG_PRINTSHARENAME,
6350 REG_SZ,
6351 buffer.data,
6352 buffer.length);
6353 if (!W_ERROR_IS_OK(result)) {
6354 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
6355 goto done;
6358 if (!force_update) {
6359 notify_printer_sharename(server_event_context(),
6360 msg_ctx,
6361 snum, printer->sharename ?
6362 printer->sharename : "");
6366 if (printer->printername != NULL &&
6367 (force_update ||
6368 !strequal(printer->printername, old_printer->printername))) {
6369 const char *p;
6371 p = strrchr(printer->printername, '\\' );
6372 if (p != NULL) {
6373 p++;
6374 } else {
6375 p = printer->printername;
6378 ok = push_reg_sz(tmp_ctx, &buffer, p);
6379 if (!ok) {
6380 DEBUG(0, ("printername data corrupted\n"));
6381 result = WERR_INVALID_DATA;
6382 goto done;
6384 result = winreg_set_printer_dataex(tmp_ctx, b,
6385 printer->sharename,
6386 SPOOL_DSSPOOLER_KEY,
6387 SPOOL_REG_PRINTERNAME,
6388 REG_SZ,
6389 buffer.data,
6390 buffer.length);
6391 if (!W_ERROR_IS_OK(result)) {
6392 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
6393 goto done;
6396 if (!force_update) {
6397 notify_printer_printername(server_event_context(),
6398 msg_ctx, snum, p ? p : "");
6402 if (printer->portname != NULL &&
6403 (force_update ||
6404 !strequal(printer->portname, old_printer->portname))) {
6405 ok = push_reg_sz(tmp_ctx, &buffer, printer->portname);
6406 if (!ok) {
6407 DEBUG(0, ("portname data corrupted\n"));
6408 result = WERR_INVALID_DATA;
6409 goto done;
6411 result = winreg_set_printer_dataex(tmp_ctx, b,
6412 printer->sharename,
6413 SPOOL_DSSPOOLER_KEY,
6414 SPOOL_REG_PORTNAME,
6415 REG_SZ,
6416 buffer.data,
6417 buffer.length);
6418 if (!W_ERROR_IS_OK(result)) {
6419 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PORTNAME));
6420 goto done;
6423 if (!force_update) {
6424 notify_printer_port(server_event_context(),
6425 msg_ctx, snum, printer->portname ?
6426 printer->portname : "");
6430 if (printer->location != NULL &&
6431 (force_update ||
6432 !strequal(printer->location, old_printer->location))) {
6433 ok = push_reg_sz(tmp_ctx, &buffer, printer->location);
6434 if (!ok) {
6435 DEBUG(0, ("location data corrupted\n"));
6436 result = WERR_INVALID_DATA;
6437 goto done;
6439 result = winreg_set_printer_dataex(tmp_ctx, b,
6440 printer->sharename,
6441 SPOOL_DSSPOOLER_KEY,
6442 SPOOL_REG_LOCATION,
6443 REG_SZ,
6444 buffer.data,
6445 buffer.length);
6446 if (!W_ERROR_IS_OK(result)) {
6447 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_LOCATION));
6448 goto done;
6451 if (!force_update) {
6452 notify_printer_location(server_event_context(),
6453 msg_ctx, snum,
6454 printer->location ?
6455 printer->location : "");
6459 if (printer->sepfile != NULL &&
6460 (force_update ||
6461 !strequal(printer->sepfile, old_printer->sepfile))) {
6462 ok = push_reg_sz(tmp_ctx, &buffer, printer->sepfile);
6463 if (!ok) {
6464 DEBUG(0, ("sepfile data corrupted\n"));
6465 result = WERR_INVALID_DATA;
6466 goto done;
6468 result = winreg_set_printer_dataex(tmp_ctx, b,
6469 printer->sharename,
6470 SPOOL_DSSPOOLER_KEY,
6471 SPOOL_REG_PRINTSEPARATORFILE,
6472 REG_SZ,
6473 buffer.data,
6474 buffer.length);
6475 if (!W_ERROR_IS_OK(result)) {
6476 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSEPARATORFILE));
6477 goto done;
6480 if (!force_update) {
6481 notify_printer_sepfile(server_event_context(),
6482 msg_ctx, snum,
6483 printer->sepfile ?
6484 printer->sepfile : "");
6488 if (printer->starttime != 0 &&
6489 (force_update ||
6490 printer->starttime != old_printer->starttime)) {
6491 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6492 SIVAL(buffer.data, 0, printer->starttime);
6493 result = winreg_set_printer_dataex(tmp_ctx, b,
6494 printer->sharename,
6495 SPOOL_DSSPOOLER_KEY,
6496 SPOOL_REG_PRINTSTARTTIME,
6497 REG_DWORD,
6498 buffer.data,
6499 buffer.length);
6500 if (!W_ERROR_IS_OK(result)) {
6501 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSTARTTIME));
6502 goto done;
6506 if (printer->untiltime != 0 &&
6507 (force_update ||
6508 printer->untiltime != old_printer->untiltime)) {
6509 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6510 SIVAL(buffer.data, 0, printer->untiltime);
6511 result = winreg_set_printer_dataex(tmp_ctx, b,
6512 printer->sharename,
6513 SPOOL_DSSPOOLER_KEY,
6514 SPOOL_REG_PRINTENDTIME,
6515 REG_DWORD,
6516 buffer.data,
6517 buffer.length);
6518 if (!W_ERROR_IS_OK(result)) {
6519 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6520 goto done;
6524 if (force_update || printer->priority != old_printer->priority) {
6525 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6526 SIVAL(buffer.data, 0, printer->priority);
6527 result = winreg_set_printer_dataex(tmp_ctx, b,
6528 printer->sharename,
6529 SPOOL_DSSPOOLER_KEY,
6530 SPOOL_REG_PRIORITY,
6531 REG_DWORD,
6532 buffer.data,
6533 buffer.length);
6534 if (!W_ERROR_IS_OK(result)) {
6535 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6536 goto done;
6540 if (force_update || printer->attributes != old_printer->attributes) {
6541 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6542 SIVAL(buffer.data, 0, (printer->attributes &
6543 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6544 result = winreg_set_printer_dataex(tmp_ctx, b,
6545 printer->sharename,
6546 SPOOL_DSSPOOLER_KEY,
6547 SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6548 REG_DWORD,
6549 buffer.data,
6550 buffer.length);
6551 if (!W_ERROR_IS_OK(result)) {
6552 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6553 goto done;
6556 switch (printer->attributes & 0x3) {
6557 case 0:
6558 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6559 break;
6560 case 1:
6561 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6562 break;
6563 case 2:
6564 spooling = SPOOL_REGVAL_PRINTDIRECT;
6565 break;
6566 default:
6567 spooling = "unknown";
6569 ok = push_reg_sz(tmp_ctx, &buffer, spooling);
6570 if (!ok) {
6571 DEBUG(0, ("printSpooling data corrupted\n"));
6572 result = WERR_INVALID_DATA;
6573 goto done;
6575 winreg_set_printer_dataex(tmp_ctx, b,
6576 printer->sharename,
6577 SPOOL_DSSPOOLER_KEY,
6578 SPOOL_REG_PRINTSPOOLING,
6579 REG_SZ,
6580 buffer.data,
6581 buffer.length);
6584 ok = push_reg_sz(tmp_ctx, &buffer, lp_netbios_name());
6585 if (!ok) {
6586 DEBUG(0, ("shortServerName data corrupted\n"));
6587 result = WERR_INVALID_DATA;
6588 goto done;
6590 result = winreg_set_printer_dataex(tmp_ctx, b,
6591 printer->sharename,
6592 SPOOL_DSSPOOLER_KEY,
6593 SPOOL_REG_SHORTSERVERNAME,
6594 REG_SZ,
6595 buffer.data,
6596 buffer.length);
6597 if (!W_ERROR_IS_OK(result)) {
6598 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SHORTSERVERNAME));
6599 goto done;
6602 dnsdomname = get_mydnsfullname();
6603 if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6604 longname = talloc_strdup(tmp_ctx, dnsdomname);
6605 } else {
6606 longname = talloc_strdup(tmp_ctx, lp_netbios_name());
6608 if (longname == NULL) {
6609 result = WERR_NOMEM;
6610 goto done;
6613 ok = push_reg_sz(tmp_ctx, &buffer, longname);
6614 if (!ok) {
6615 DEBUG(0, ("longname data corrupted\n"));
6616 result = WERR_INVALID_DATA;
6617 goto done;
6619 result = winreg_set_printer_dataex(tmp_ctx, b,
6620 printer->sharename,
6621 SPOOL_DSSPOOLER_KEY,
6622 SPOOL_REG_SERVERNAME,
6623 REG_SZ,
6624 buffer.data,
6625 buffer.length);
6626 if (!W_ERROR_IS_OK(result)) {
6627 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SERVERNAME));
6628 goto done;
6631 uncname = talloc_asprintf(tmp_ctx, "\\\\%s\\%s",
6632 lp_netbios_name(), printer->sharename);
6633 ok = push_reg_sz(tmp_ctx, &buffer, uncname);
6634 if (!ok) {
6635 DEBUG(0, ("uncName data corrupted\n"));
6636 result = WERR_INVALID_DATA;
6637 goto done;
6639 result = winreg_set_printer_dataex(tmp_ctx, b,
6640 printer->sharename,
6641 SPOOL_DSSPOOLER_KEY,
6642 SPOOL_REG_UNCNAME,
6643 REG_SZ,
6644 buffer.data,
6645 buffer.length);
6646 if (!W_ERROR_IS_OK(result)) {
6647 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_UNCNAME));
6648 goto done;
6651 done:
6652 talloc_free(tmp_ctx);
6653 return result;
6656 /********************************************************************
6657 * Called by spoolss_api_setprinter
6658 * when updating a printer description.
6659 ********************************************************************/
6661 static WERROR update_printer(struct pipes_struct *p,
6662 struct policy_handle *handle,
6663 struct spoolss_SetPrinterInfoCtr *info_ctr,
6664 struct spoolss_DeviceMode *devmode)
6666 uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6667 struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6668 struct spoolss_PrinterInfo2 *old_printer;
6669 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6670 int snum;
6671 WERROR result = WERR_OK;
6672 TALLOC_CTX *tmp_ctx;
6673 struct dcerpc_binding_handle *b;
6675 DEBUG(8,("update_printer\n"));
6677 tmp_ctx = talloc_new(p->mem_ctx);
6678 if (tmp_ctx == NULL) {
6679 return WERR_NOMEM;
6682 if (!Printer) {
6683 result = WERR_BADFID;
6684 goto done;
6687 if (!get_printer_snum(p, handle, &snum, NULL)) {
6688 result = WERR_BADFID;
6689 goto done;
6692 result = winreg_printer_binding_handle(tmp_ctx,
6693 get_session_info_system(),
6694 p->msg_ctx,
6695 &b);
6696 if (!W_ERROR_IS_OK(result)) {
6697 goto done;
6700 result = winreg_get_printer(tmp_ctx, b,
6701 lp_const_servicename(snum),
6702 &old_printer);
6703 if (!W_ERROR_IS_OK(result)) {
6704 result = WERR_BADFID;
6705 goto done;
6708 /* Do sanity check on the requested changes for Samba */
6709 if (!check_printer_ok(tmp_ctx, printer, snum)) {
6710 result = WERR_INVALID_PARAM;
6711 goto done;
6714 /* FIXME!!! If the driver has changed we really should verify that
6715 it is installed before doing much else --jerry */
6717 /* Check calling user has permission to update printer description */
6718 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6719 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6720 result = WERR_ACCESS_DENIED;
6721 goto done;
6724 /* Call addprinter hook */
6725 /* Check changes to see if this is really needed */
6727 if (*lp_addprinter_cmd(talloc_tos()) &&
6728 (!strequal(printer->drivername, old_printer->drivername) ||
6729 !strequal(printer->comment, old_printer->comment) ||
6730 !strequal(printer->portname, old_printer->portname) ||
6731 !strequal(printer->location, old_printer->location)) )
6733 char *raddr;
6735 raddr = tsocket_address_inet_addr_string(p->remote_address,
6736 p->mem_ctx);
6737 if (raddr == NULL) {
6738 return WERR_NOMEM;
6741 /* add_printer_hook() will call reload_services() */
6742 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6743 printer, raddr,
6744 p->msg_ctx)) {
6745 result = WERR_ACCESS_DENIED;
6746 goto done;
6750 result = update_dsspooler(tmp_ctx,
6751 get_session_info_system(),
6752 p->msg_ctx,
6753 snum,
6754 printer,
6755 old_printer);
6756 if (!W_ERROR_IS_OK(result)) {
6757 goto done;
6760 printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6762 if (devmode == NULL) {
6763 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6765 result = winreg_update_printer(tmp_ctx, b,
6766 printer->sharename,
6767 printer_mask,
6768 printer,
6769 devmode,
6770 NULL);
6772 done:
6773 talloc_free(tmp_ctx);
6775 return result;
6778 /****************************************************************************
6779 ****************************************************************************/
6780 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6781 struct policy_handle *handle,
6782 struct spoolss_SetPrinterInfo7 *info7)
6784 #ifdef HAVE_ADS
6785 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6786 WERROR result;
6787 int snum;
6788 struct printer_handle *Printer;
6790 if ( lp_security() != SEC_ADS ) {
6791 return WERR_UNKNOWN_LEVEL;
6794 Printer = find_printer_index_by_hnd(p, handle);
6796 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6798 if (!Printer)
6799 return WERR_BADFID;
6801 if (!get_printer_snum(p, handle, &snum, NULL))
6802 return WERR_BADFID;
6804 result = winreg_get_printer_internal(p->mem_ctx,
6805 get_session_info_system(),
6806 p->msg_ctx,
6807 lp_servicename(talloc_tos(), snum),
6808 &pinfo2);
6809 if (!W_ERROR_IS_OK(result)) {
6810 return WERR_BADFID;
6813 nt_printer_publish(pinfo2,
6814 get_session_info_system(),
6815 p->msg_ctx,
6816 pinfo2,
6817 info7->action);
6819 TALLOC_FREE(pinfo2);
6820 return WERR_OK;
6821 #else
6822 return WERR_UNKNOWN_LEVEL;
6823 #endif
6826 /********************************************************************
6827 ********************************************************************/
6829 static WERROR update_printer_devmode(struct pipes_struct *p,
6830 struct policy_handle *handle,
6831 struct spoolss_DeviceMode *devmode)
6833 int snum;
6834 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6835 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6837 DEBUG(8,("update_printer_devmode\n"));
6839 if (!Printer) {
6840 return WERR_BADFID;
6843 if (!get_printer_snum(p, handle, &snum, NULL)) {
6844 return WERR_BADFID;
6847 /* Check calling user has permission to update printer description */
6848 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6849 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6850 return WERR_ACCESS_DENIED;
6853 return winreg_update_printer_internal(p->mem_ctx,
6854 get_session_info_system(),
6855 p->msg_ctx,
6856 lp_const_servicename(snum),
6857 info2_mask,
6858 NULL,
6859 devmode,
6860 NULL);
6864 /****************************************************************
6865 _spoolss_SetPrinter
6866 ****************************************************************/
6868 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6869 struct spoolss_SetPrinter *r)
6871 WERROR result;
6873 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6875 if (!Printer) {
6876 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6877 OUR_HANDLE(r->in.handle)));
6878 return WERR_BADFID;
6881 /* check the level */
6882 switch (r->in.info_ctr->level) {
6883 case 0:
6884 return control_printer(r->in.handle, r->in.command, p);
6885 case 2:
6886 result = update_printer(p, r->in.handle,
6887 r->in.info_ctr,
6888 r->in.devmode_ctr->devmode);
6889 if (!W_ERROR_IS_OK(result))
6890 return result;
6891 if (r->in.secdesc_ctr->sd)
6892 result = update_printer_sec(r->in.handle, p,
6893 r->in.secdesc_ctr);
6894 return result;
6895 case 3:
6896 return update_printer_sec(r->in.handle, p,
6897 r->in.secdesc_ctr);
6898 case 7:
6899 return publish_or_unpublish_printer(p, r->in.handle,
6900 r->in.info_ctr->info.info7);
6901 case 8:
6902 return update_printer_devmode(p, r->in.handle,
6903 r->in.devmode_ctr->devmode);
6904 default:
6905 return WERR_UNKNOWN_LEVEL;
6909 /****************************************************************
6910 _spoolss_FindClosePrinterNotify
6911 ****************************************************************/
6913 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
6914 struct spoolss_FindClosePrinterNotify *r)
6916 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6918 if (!Printer) {
6919 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6920 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6921 return WERR_BADFID;
6924 if (Printer->notify.cli_chan != NULL &&
6925 Printer->notify.cli_chan->active_connections > 0) {
6926 int snum = -1;
6928 if (Printer->printer_type == SPLHND_PRINTER) {
6929 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6930 return WERR_BADFID;
6934 srv_spoolss_replycloseprinter(snum, Printer);
6937 Printer->notify.flags=0;
6938 Printer->notify.options=0;
6939 Printer->notify.localmachine[0]='\0';
6940 Printer->notify.printerlocal=0;
6941 TALLOC_FREE(Printer->notify.option);
6943 return WERR_OK;
6946 /****************************************************************
6947 _spoolss_AddJob
6948 ****************************************************************/
6950 WERROR _spoolss_AddJob(struct pipes_struct *p,
6951 struct spoolss_AddJob *r)
6953 if (!r->in.buffer && (r->in.offered != 0)) {
6954 return WERR_INVALID_PARAM;
6957 /* this is what a NT server returns for AddJob. AddJob must fail on
6958 * non-local printers */
6960 if (r->in.level != 1) {
6961 return WERR_UNKNOWN_LEVEL;
6964 return WERR_INVALID_PARAM;
6967 /****************************************************************************
6968 fill_job_info1
6969 ****************************************************************************/
6971 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6972 struct spoolss_JobInfo1 *r,
6973 const print_queue_struct *queue,
6974 int position, int snum,
6975 struct spoolss_PrinterInfo2 *pinfo2)
6977 struct tm *t;
6979 t = gmtime(&queue->time);
6981 r->job_id = queue->sysjob;
6983 r->printer_name = lp_servicename(mem_ctx, snum);
6984 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6985 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
6986 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6987 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6988 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6989 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6990 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6991 r->data_type = talloc_strdup(mem_ctx, "RAW");
6992 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6993 r->text_status = talloc_strdup(mem_ctx, "");
6994 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6996 r->status = nt_printj_status(queue->status);
6997 r->priority = queue->priority;
6998 r->position = position;
6999 r->total_pages = queue->page_count;
7000 r->pages_printed = 0; /* ??? */
7002 init_systemtime(&r->submitted, t);
7004 return WERR_OK;
7007 /****************************************************************************
7008 fill_job_info2
7009 ****************************************************************************/
7011 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
7012 struct spoolss_JobInfo2 *r,
7013 const print_queue_struct *queue,
7014 int position, int snum,
7015 struct spoolss_PrinterInfo2 *pinfo2,
7016 struct spoolss_DeviceMode *devmode)
7018 struct tm *t;
7020 t = gmtime(&queue->time);
7022 r->job_id = queue->sysjob;
7024 r->printer_name = lp_servicename(mem_ctx, snum);
7025 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
7026 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
7027 W_ERROR_HAVE_NO_MEMORY(r->server_name);
7028 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
7029 W_ERROR_HAVE_NO_MEMORY(r->user_name);
7030 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
7031 W_ERROR_HAVE_NO_MEMORY(r->document_name);
7032 r->notify_name = talloc_strdup(mem_ctx, queue->fs_user);
7033 W_ERROR_HAVE_NO_MEMORY(r->notify_name);
7034 r->data_type = talloc_strdup(mem_ctx, "RAW");
7035 W_ERROR_HAVE_NO_MEMORY(r->data_type);
7036 r->print_processor = talloc_strdup(mem_ctx, "winprint");
7037 W_ERROR_HAVE_NO_MEMORY(r->print_processor);
7038 r->parameters = talloc_strdup(mem_ctx, "");
7039 W_ERROR_HAVE_NO_MEMORY(r->parameters);
7040 r->driver_name = talloc_strdup(mem_ctx, pinfo2->drivername);
7041 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
7043 r->devmode = devmode;
7045 r->text_status = talloc_strdup(mem_ctx, "");
7046 W_ERROR_HAVE_NO_MEMORY(r->text_status);
7048 r->secdesc = NULL;
7050 r->status = nt_printj_status(queue->status);
7051 r->priority = queue->priority;
7052 r->position = position;
7053 r->start_time = 0;
7054 r->until_time = 0;
7055 r->total_pages = queue->page_count;
7056 r->size = queue->size;
7057 init_systemtime(&r->submitted, t);
7058 r->time = 0;
7059 r->pages_printed = 0; /* ??? */
7061 return WERR_OK;
7064 /****************************************************************************
7065 fill_job_info3
7066 ****************************************************************************/
7068 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
7069 struct spoolss_JobInfo3 *r,
7070 const print_queue_struct *queue,
7071 const print_queue_struct *next_queue,
7072 int position, int snum,
7073 struct spoolss_PrinterInfo2 *pinfo2)
7075 r->job_id = queue->sysjob;
7076 r->next_job_id = 0;
7077 if (next_queue) {
7078 r->next_job_id = next_queue->sysjob;
7080 r->reserved = 0;
7082 return WERR_OK;
7085 /****************************************************************************
7086 Enumjobs at level 1.
7087 ****************************************************************************/
7089 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
7090 const print_queue_struct *queue,
7091 uint32_t num_queues, int snum,
7092 struct spoolss_PrinterInfo2 *pinfo2,
7093 union spoolss_JobInfo **info_p,
7094 uint32_t *count)
7096 union spoolss_JobInfo *info;
7097 int i;
7098 WERROR result = WERR_OK;
7100 info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7101 W_ERROR_HAVE_NO_MEMORY(info);
7103 *count = num_queues;
7105 for (i=0; i<*count; i++) {
7106 result = fill_job_info1(info,
7107 &info[i].info1,
7108 &queue[i],
7110 snum,
7111 pinfo2);
7112 if (!W_ERROR_IS_OK(result)) {
7113 goto out;
7117 out:
7118 if (!W_ERROR_IS_OK(result)) {
7119 TALLOC_FREE(info);
7120 *count = 0;
7121 return result;
7124 *info_p = info;
7126 return WERR_OK;
7129 /****************************************************************************
7130 Enumjobs at level 2.
7131 ****************************************************************************/
7133 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
7134 const print_queue_struct *queue,
7135 uint32_t num_queues, int snum,
7136 struct spoolss_PrinterInfo2 *pinfo2,
7137 union spoolss_JobInfo **info_p,
7138 uint32_t *count)
7140 union spoolss_JobInfo *info;
7141 int i;
7142 WERROR result = WERR_OK;
7144 info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7145 W_ERROR_HAVE_NO_MEMORY(info);
7147 *count = num_queues;
7149 for (i=0; i<*count; i++) {
7150 struct spoolss_DeviceMode *devmode;
7152 result = spoolss_create_default_devmode(info,
7153 pinfo2->printername,
7154 &devmode);
7155 if (!W_ERROR_IS_OK(result)) {
7156 DEBUG(3, ("Can't proceed w/o a devmode!"));
7157 goto out;
7160 result = fill_job_info2(info,
7161 &info[i].info2,
7162 &queue[i],
7164 snum,
7165 pinfo2,
7166 devmode);
7167 if (!W_ERROR_IS_OK(result)) {
7168 goto out;
7172 out:
7173 if (!W_ERROR_IS_OK(result)) {
7174 TALLOC_FREE(info);
7175 *count = 0;
7176 return result;
7179 *info_p = info;
7181 return WERR_OK;
7184 /****************************************************************************
7185 Enumjobs at level 3.
7186 ****************************************************************************/
7188 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
7189 const print_queue_struct *queue,
7190 uint32_t num_queues, int snum,
7191 struct spoolss_PrinterInfo2 *pinfo2,
7192 union spoolss_JobInfo **info_p,
7193 uint32_t *count)
7195 union spoolss_JobInfo *info;
7196 int i;
7197 WERROR result = WERR_OK;
7199 info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7200 W_ERROR_HAVE_NO_MEMORY(info);
7202 *count = num_queues;
7204 for (i=0; i<*count; i++) {
7205 const print_queue_struct *next_queue = NULL;
7207 if (i+1 < *count) {
7208 next_queue = &queue[i+1];
7211 result = fill_job_info3(info,
7212 &info[i].info3,
7213 &queue[i],
7214 next_queue,
7216 snum,
7217 pinfo2);
7218 if (!W_ERROR_IS_OK(result)) {
7219 goto out;
7223 out:
7224 if (!W_ERROR_IS_OK(result)) {
7225 TALLOC_FREE(info);
7226 *count = 0;
7227 return result;
7230 *info_p = info;
7232 return WERR_OK;
7235 /****************************************************************
7236 _spoolss_EnumJobs
7237 ****************************************************************/
7239 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7240 struct spoolss_EnumJobs *r)
7242 WERROR result;
7243 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7244 int snum;
7245 print_status_struct prt_status;
7246 print_queue_struct *queue = NULL;
7247 uint32_t count;
7249 /* that's an [in out] buffer */
7251 if (!r->in.buffer && (r->in.offered != 0)) {
7252 return WERR_INVALID_PARAM;
7255 DEBUG(4,("_spoolss_EnumJobs\n"));
7257 *r->out.needed = 0;
7258 *r->out.count = 0;
7259 *r->out.info = NULL;
7261 /* lookup the printer snum and tdb entry */
7263 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7264 return WERR_BADFID;
7267 result = winreg_get_printer_internal(p->mem_ctx,
7268 get_session_info_system(),
7269 p->msg_ctx,
7270 lp_const_servicename(snum),
7271 &pinfo2);
7272 if (!W_ERROR_IS_OK(result)) {
7273 return result;
7276 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7277 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7278 count, prt_status.status, prt_status.message));
7280 if (count == 0) {
7281 SAFE_FREE(queue);
7282 TALLOC_FREE(pinfo2);
7283 return WERR_OK;
7286 switch (r->in.level) {
7287 case 1:
7288 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7289 pinfo2, r->out.info, r->out.count);
7290 break;
7291 case 2:
7292 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7293 pinfo2, r->out.info, r->out.count);
7294 break;
7295 case 3:
7296 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7297 pinfo2, r->out.info, r->out.count);
7298 break;
7299 default:
7300 result = WERR_UNKNOWN_LEVEL;
7301 break;
7304 SAFE_FREE(queue);
7305 TALLOC_FREE(pinfo2);
7307 if (!W_ERROR_IS_OK(result)) {
7308 return result;
7311 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7312 spoolss_EnumJobs,
7313 *r->out.info, r->in.level,
7314 *r->out.count);
7315 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7316 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7318 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7321 /****************************************************************
7322 _spoolss_ScheduleJob
7323 ****************************************************************/
7325 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7326 struct spoolss_ScheduleJob *r)
7328 return WERR_OK;
7331 /****************************************************************
7332 ****************************************************************/
7334 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7335 struct messaging_context *msg_ctx,
7336 const char *printer_name,
7337 uint32_t job_id,
7338 struct spoolss_SetJobInfo1 *r)
7340 char *old_doc_name;
7342 if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7343 return WERR_BADFID;
7346 if (strequal(old_doc_name, r->document_name)) {
7347 return WERR_OK;
7350 if (!print_job_set_name(server_event_context(), msg_ctx,
7351 printer_name, job_id, r->document_name)) {
7352 return WERR_BADFID;
7355 return WERR_OK;
7358 /****************************************************************
7359 _spoolss_SetJob
7360 ****************************************************************/
7362 WERROR _spoolss_SetJob(struct pipes_struct *p,
7363 struct spoolss_SetJob *r)
7365 const struct auth_session_info *session_info = p->session_info;
7366 int snum;
7367 WERROR errcode = WERR_BADFUNC;
7369 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7370 return WERR_BADFID;
7373 if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7374 return WERR_INVALID_PRINTER_NAME;
7377 switch (r->in.command) {
7378 case SPOOLSS_JOB_CONTROL_CANCEL:
7379 case SPOOLSS_JOB_CONTROL_DELETE:
7380 errcode = print_job_delete(session_info, p->msg_ctx,
7381 snum, r->in.job_id);
7382 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7383 errcode = WERR_OK;
7385 break;
7386 case SPOOLSS_JOB_CONTROL_PAUSE:
7387 errcode = print_job_pause(session_info, p->msg_ctx,
7388 snum, r->in.job_id);
7389 break;
7390 case SPOOLSS_JOB_CONTROL_RESTART:
7391 case SPOOLSS_JOB_CONTROL_RESUME:
7392 errcode = print_job_resume(session_info, p->msg_ctx,
7393 snum, r->in.job_id);
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(talloc_tos());
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(talloc_tos()) ) {
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;
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,
8671 SEC_PRIV_PRINT_OPERATOR)) {
8672 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8673 return WERR_ACCESS_DENIED;
8676 if (r->in.info_ctr->level != 1) {
8677 return WERR_INVALID_LEVEL;
8680 form = r->in.info_ctr->info.info1;
8681 if (!form) {
8682 return WERR_INVALID_PARAM;
8685 switch (form->flags) {
8686 case SPOOLSS_FORM_USER:
8687 case SPOOLSS_FORM_BUILTIN:
8688 case SPOOLSS_FORM_PRINTER:
8689 break;
8690 default:
8691 return WERR_INVALID_PARAM;
8694 tmp_ctx = talloc_new(p->mem_ctx);
8695 if (!tmp_ctx) {
8696 return WERR_NOMEM;
8699 status = winreg_printer_binding_handle(tmp_ctx,
8700 get_session_info_system(),
8701 p->msg_ctx,
8702 &b);
8703 if (!W_ERROR_IS_OK(status)) {
8704 goto done;
8707 status = winreg_printer_addform1(tmp_ctx, b, form);
8708 if (!W_ERROR_IS_OK(status)) {
8709 goto done;
8713 * ChangeID must always be set if this is a printer
8715 if (Printer->printer_type == SPLHND_PRINTER) {
8716 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8717 status = WERR_BADFID;
8718 goto done;
8721 status = winreg_printer_update_changeid(tmp_ctx, b,
8722 lp_const_servicename(snum));
8725 done:
8726 talloc_free(tmp_ctx);
8727 return status;
8730 /****************************************************************
8731 _spoolss_DeleteForm
8732 ****************************************************************/
8734 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8735 struct spoolss_DeleteForm *r)
8737 const char *form_name = r->in.form_name;
8738 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8739 int snum = -1;
8740 WERROR status = WERR_OK;
8741 struct dcerpc_binding_handle *b;
8742 TALLOC_CTX *tmp_ctx = NULL;
8744 DEBUG(5,("_spoolss_DeleteForm\n"));
8746 if (!Printer) {
8747 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8748 OUR_HANDLE(r->in.handle)));
8749 return WERR_BADFID;
8752 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8753 !security_token_has_privilege(p->session_info->security_token,
8754 SEC_PRIV_PRINT_OPERATOR)) {
8755 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8756 return WERR_ACCESS_DENIED;
8759 tmp_ctx = talloc_new(p->mem_ctx);
8760 if (!tmp_ctx) {
8761 return WERR_NOMEM;
8764 status = winreg_printer_binding_handle(tmp_ctx,
8765 get_session_info_system(),
8766 p->msg_ctx,
8767 &b);
8768 if (!W_ERROR_IS_OK(status)) {
8769 goto done;
8772 status = winreg_printer_deleteform1(tmp_ctx, b, form_name);
8773 if (!W_ERROR_IS_OK(status)) {
8774 goto done;
8778 * ChangeID must always be set if this is a printer
8780 if (Printer->printer_type == SPLHND_PRINTER) {
8781 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8782 status = WERR_BADFID;
8783 goto done;
8786 status = winreg_printer_update_changeid(tmp_ctx, b,
8787 lp_const_servicename(snum));
8790 done:
8791 talloc_free(tmp_ctx);
8792 return status;
8795 /****************************************************************
8796 _spoolss_SetForm
8797 ****************************************************************/
8799 WERROR _spoolss_SetForm(struct pipes_struct *p,
8800 struct spoolss_SetForm *r)
8802 struct spoolss_AddFormInfo1 *form;
8803 const char *form_name = r->in.form_name;
8804 int snum = -1;
8805 WERROR status = WERR_OK;
8806 struct dcerpc_binding_handle *b;
8807 TALLOC_CTX *tmp_ctx = NULL;
8809 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8811 DEBUG(5,("_spoolss_SetForm\n"));
8813 if (!Printer) {
8814 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8815 OUR_HANDLE(r->in.handle)));
8816 return WERR_BADFID;
8819 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8820 and not a printer admin, then fail */
8822 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8823 !security_token_has_privilege(p->session_info->security_token,
8824 SEC_PRIV_PRINT_OPERATOR)) {
8825 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8826 return WERR_ACCESS_DENIED;
8829 if (r->in.info_ctr->level != 1) {
8830 return WERR_INVALID_LEVEL;
8833 form = r->in.info_ctr->info.info1;
8834 if (!form) {
8835 return WERR_INVALID_PARAM;
8838 tmp_ctx = talloc_new(p->mem_ctx);
8839 if (!tmp_ctx) {
8840 return WERR_NOMEM;
8843 status = winreg_printer_binding_handle(tmp_ctx,
8844 get_session_info_system(),
8845 p->msg_ctx,
8846 &b);
8847 if (!W_ERROR_IS_OK(status)) {
8848 goto done;
8851 status = winreg_printer_setform1(tmp_ctx, b,
8852 form_name,
8853 form);
8854 if (!W_ERROR_IS_OK(status)) {
8855 goto done;
8859 * ChangeID must always be set if this is a printer
8861 if (Printer->printer_type == SPLHND_PRINTER) {
8862 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8863 status = WERR_BADFID;
8864 goto done;
8867 status = winreg_printer_update_changeid(tmp_ctx, b,
8868 lp_const_servicename(snum));
8871 done:
8872 talloc_free(tmp_ctx);
8873 return status;
8876 /****************************************************************************
8877 fill_print_processor1
8878 ****************************************************************************/
8880 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8881 struct spoolss_PrintProcessorInfo1 *r,
8882 const char *print_processor_name)
8884 r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8885 W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8887 return WERR_OK;
8890 /****************************************************************************
8891 enumprintprocessors level 1.
8892 ****************************************************************************/
8894 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8895 union spoolss_PrintProcessorInfo **info_p,
8896 uint32_t *count)
8898 union spoolss_PrintProcessorInfo *info;
8899 WERROR result;
8901 info = talloc_array(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8902 W_ERROR_HAVE_NO_MEMORY(info);
8904 *count = 1;
8906 result = fill_print_processor1(info, &info[0].info1, "winprint");
8907 if (!W_ERROR_IS_OK(result)) {
8908 goto out;
8911 out:
8912 if (!W_ERROR_IS_OK(result)) {
8913 TALLOC_FREE(info);
8914 *count = 0;
8915 return result;
8918 *info_p = info;
8920 return WERR_OK;
8923 /****************************************************************
8924 _spoolss_EnumPrintProcessors
8925 ****************************************************************/
8927 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
8928 struct spoolss_EnumPrintProcessors *r)
8930 WERROR result;
8932 /* that's an [in out] buffer */
8934 if (!r->in.buffer && (r->in.offered != 0)) {
8935 return WERR_INVALID_PARAM;
8938 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8941 * Enumerate the print processors ...
8943 * Just reply with "winprint", to keep NT happy
8944 * and I can use my nice printer checker.
8947 *r->out.count = 0;
8948 *r->out.needed = 0;
8949 *r->out.info = NULL;
8951 if (!get_short_archi(r->in.environment)) {
8952 return WERR_INVALID_ENVIRONMENT;
8955 switch (r->in.level) {
8956 case 1:
8957 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8958 r->out.count);
8959 break;
8960 default:
8961 return WERR_UNKNOWN_LEVEL;
8964 if (!W_ERROR_IS_OK(result)) {
8965 return result;
8968 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8969 spoolss_EnumPrintProcessors,
8970 *r->out.info, r->in.level,
8971 *r->out.count);
8972 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8973 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8975 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8978 /****************************************************************************
8979 fill_printprocdatatype1
8980 ****************************************************************************/
8982 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8983 struct spoolss_PrintProcDataTypesInfo1 *r,
8984 const char *name_array)
8986 r->name_array = talloc_strdup(mem_ctx, name_array);
8987 W_ERROR_HAVE_NO_MEMORY(r->name_array);
8989 return WERR_OK;
8992 /****************************************************************************
8993 enumprintprocdatatypes level 1.
8994 ****************************************************************************/
8996 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8997 union spoolss_PrintProcDataTypesInfo **info_p,
8998 uint32_t *count)
9000 WERROR result;
9001 union spoolss_PrintProcDataTypesInfo *info;
9003 info = talloc_array(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
9004 W_ERROR_HAVE_NO_MEMORY(info);
9006 *count = 1;
9008 result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
9009 if (!W_ERROR_IS_OK(result)) {
9010 goto out;
9013 out:
9014 if (!W_ERROR_IS_OK(result)) {
9015 TALLOC_FREE(info);
9016 *count = 0;
9017 return result;
9020 *info_p = info;
9022 return WERR_OK;
9025 /****************************************************************
9026 _spoolss_EnumPrintProcDataTypes
9027 ****************************************************************/
9029 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
9030 struct spoolss_EnumPrintProcDataTypes *r)
9032 WERROR result;
9034 /* that's an [in out] buffer */
9036 if (!r->in.buffer && (r->in.offered != 0)) {
9037 return WERR_INVALID_PARAM;
9040 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
9042 *r->out.count = 0;
9043 *r->out.needed = 0;
9044 *r->out.info = NULL;
9046 if (r->in.print_processor_name == NULL ||
9047 !strequal(r->in.print_processor_name, "winprint")) {
9048 return WERR_UNKNOWN_PRINTPROCESSOR;
9051 switch (r->in.level) {
9052 case 1:
9053 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
9054 r->out.count);
9055 break;
9056 default:
9057 return WERR_UNKNOWN_LEVEL;
9060 if (!W_ERROR_IS_OK(result)) {
9061 return result;
9064 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9065 spoolss_EnumPrintProcDataTypes,
9066 *r->out.info, r->in.level,
9067 *r->out.count);
9068 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9069 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9071 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9074 /****************************************************************************
9075 fill_monitor_1
9076 ****************************************************************************/
9078 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
9079 struct spoolss_MonitorInfo1 *r,
9080 const char *monitor_name)
9082 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
9083 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9085 return WERR_OK;
9088 /****************************************************************************
9089 fill_monitor_2
9090 ****************************************************************************/
9092 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
9093 struct spoolss_MonitorInfo2 *r,
9094 const char *monitor_name,
9095 const char *environment,
9096 const char *dll_name)
9098 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
9099 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9100 r->environment = talloc_strdup(mem_ctx, environment);
9101 W_ERROR_HAVE_NO_MEMORY(r->environment);
9102 r->dll_name = talloc_strdup(mem_ctx, dll_name);
9103 W_ERROR_HAVE_NO_MEMORY(r->dll_name);
9105 return WERR_OK;
9108 /****************************************************************************
9109 enumprintmonitors level 1.
9110 ****************************************************************************/
9112 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
9113 union spoolss_MonitorInfo **info_p,
9114 uint32_t *count)
9116 union spoolss_MonitorInfo *info;
9117 WERROR result = WERR_OK;
9119 info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9120 W_ERROR_HAVE_NO_MEMORY(info);
9122 *count = 2;
9124 result = fill_monitor_1(info, &info[0].info1,
9125 SPL_LOCAL_PORT);
9126 if (!W_ERROR_IS_OK(result)) {
9127 goto out;
9130 result = fill_monitor_1(info, &info[1].info1,
9131 SPL_TCPIP_PORT);
9132 if (!W_ERROR_IS_OK(result)) {
9133 goto out;
9136 out:
9137 if (!W_ERROR_IS_OK(result)) {
9138 TALLOC_FREE(info);
9139 *count = 0;
9140 return result;
9143 *info_p = info;
9145 return WERR_OK;
9148 /****************************************************************************
9149 enumprintmonitors level 2.
9150 ****************************************************************************/
9152 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
9153 union spoolss_MonitorInfo **info_p,
9154 uint32_t *count)
9156 union spoolss_MonitorInfo *info;
9157 WERROR result = WERR_OK;
9159 info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9160 W_ERROR_HAVE_NO_MEMORY(info);
9162 *count = 2;
9164 result = fill_monitor_2(info, &info[0].info2,
9165 SPL_LOCAL_PORT,
9166 "Windows NT X86", /* FIXME */
9167 "localmon.dll");
9168 if (!W_ERROR_IS_OK(result)) {
9169 goto out;
9172 result = fill_monitor_2(info, &info[1].info2,
9173 SPL_TCPIP_PORT,
9174 "Windows NT X86", /* FIXME */
9175 "tcpmon.dll");
9176 if (!W_ERROR_IS_OK(result)) {
9177 goto out;
9180 out:
9181 if (!W_ERROR_IS_OK(result)) {
9182 TALLOC_FREE(info);
9183 *count = 0;
9184 return result;
9187 *info_p = info;
9189 return WERR_OK;
9192 /****************************************************************
9193 _spoolss_EnumMonitors
9194 ****************************************************************/
9196 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
9197 struct spoolss_EnumMonitors *r)
9199 WERROR result;
9201 /* that's an [in out] buffer */
9203 if (!r->in.buffer && (r->in.offered != 0)) {
9204 return WERR_INVALID_PARAM;
9207 DEBUG(5,("_spoolss_EnumMonitors\n"));
9210 * Enumerate the print monitors ...
9212 * Just reply with "Local Port", to keep NT happy
9213 * and I can use my nice printer checker.
9216 *r->out.count = 0;
9217 *r->out.needed = 0;
9218 *r->out.info = NULL;
9220 switch (r->in.level) {
9221 case 1:
9222 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
9223 r->out.count);
9224 break;
9225 case 2:
9226 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
9227 r->out.count);
9228 break;
9229 default:
9230 return WERR_UNKNOWN_LEVEL;
9233 if (!W_ERROR_IS_OK(result)) {
9234 return result;
9237 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9238 spoolss_EnumMonitors,
9239 *r->out.info, r->in.level,
9240 *r->out.count);
9241 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9242 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9244 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9247 /****************************************************************************
9248 ****************************************************************************/
9250 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
9251 const print_queue_struct *queue,
9252 int count, int snum,
9253 struct spoolss_PrinterInfo2 *pinfo2,
9254 uint32_t jobid,
9255 struct spoolss_JobInfo1 *r)
9257 int i = 0;
9258 bool found = false;
9260 for (i=0; i<count; i++) {
9261 if (queue[i].sysjob == (int)jobid) {
9262 found = true;
9263 break;
9267 if (found == false) {
9268 /* NT treats not found as bad param... yet another bad choice */
9269 return WERR_INVALID_PARAM;
9272 return fill_job_info1(mem_ctx,
9274 &queue[i],
9276 snum,
9277 pinfo2);
9280 /****************************************************************************
9281 ****************************************************************************/
9283 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9284 const print_queue_struct *queue,
9285 int count, int snum,
9286 struct spoolss_PrinterInfo2 *pinfo2,
9287 uint32_t jobid,
9288 struct spoolss_JobInfo2 *r)
9290 int i = 0;
9291 bool found = false;
9292 struct spoolss_DeviceMode *devmode;
9293 WERROR result;
9295 for (i=0; i<count; i++) {
9296 if (queue[i].sysjob == (int)jobid) {
9297 found = true;
9298 break;
9302 if (found == false) {
9303 /* NT treats not found as bad param... yet another bad
9304 choice */
9305 return WERR_INVALID_PARAM;
9309 * if the print job does not have a DEVMODE associated with it,
9310 * just use the one for the printer. A NULL devicemode is not
9311 * a failure condition
9314 devmode = print_job_devmode(mem_ctx, lp_const_servicename(snum), jobid);
9315 if (!devmode) {
9316 result = spoolss_create_default_devmode(mem_ctx,
9317 pinfo2->printername,
9318 &devmode);
9319 if (!W_ERROR_IS_OK(result)) {
9320 DEBUG(3, ("Can't proceed w/o a devmode!"));
9321 return result;
9325 return fill_job_info2(mem_ctx,
9327 &queue[i],
9329 snum,
9330 pinfo2,
9331 devmode);
9334 /****************************************************************
9335 _spoolss_GetJob
9336 ****************************************************************/
9338 WERROR _spoolss_GetJob(struct pipes_struct *p,
9339 struct spoolss_GetJob *r)
9341 WERROR result = WERR_OK;
9342 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9343 int snum;
9344 int count;
9345 print_queue_struct *queue = NULL;
9346 print_status_struct prt_status;
9348 /* that's an [in out] buffer */
9350 if (!r->in.buffer && (r->in.offered != 0)) {
9351 return WERR_INVALID_PARAM;
9354 DEBUG(5,("_spoolss_GetJob\n"));
9356 *r->out.needed = 0;
9358 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9359 return WERR_BADFID;
9362 result = winreg_get_printer_internal(p->mem_ctx,
9363 get_session_info_system(),
9364 p->msg_ctx,
9365 lp_const_servicename(snum),
9366 &pinfo2);
9367 if (!W_ERROR_IS_OK(result)) {
9368 return result;
9371 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9373 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9374 count, prt_status.status, prt_status.message));
9376 switch (r->in.level) {
9377 case 1:
9378 result = getjob_level_1(p->mem_ctx,
9379 queue, count, snum, pinfo2,
9380 r->in.job_id, &r->out.info->info1);
9381 break;
9382 case 2:
9383 result = getjob_level_2(p->mem_ctx,
9384 queue, count, snum, pinfo2,
9385 r->in.job_id, &r->out.info->info2);
9386 break;
9387 default:
9388 result = WERR_UNKNOWN_LEVEL;
9389 break;
9392 SAFE_FREE(queue);
9393 TALLOC_FREE(pinfo2);
9395 if (!W_ERROR_IS_OK(result)) {
9396 TALLOC_FREE(r->out.info);
9397 return result;
9400 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9401 r->in.level);
9402 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9404 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9407 /****************************************************************
9408 _spoolss_GetPrinterDataEx
9409 ****************************************************************/
9411 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9412 struct spoolss_GetPrinterDataEx *r)
9415 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9416 const char *printer;
9417 int snum = 0;
9418 WERROR result = WERR_OK;
9419 DATA_BLOB blob;
9420 enum winreg_Type val_type = REG_NONE;
9421 uint8_t *val_data = NULL;
9422 uint32_t val_size = 0;
9423 struct dcerpc_binding_handle *b;
9424 TALLOC_CTX *tmp_ctx;
9426 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9428 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9429 r->in.key_name, r->in.value_name));
9431 /* in case of problem, return some default values */
9433 *r->out.needed = 0;
9434 *r->out.type = REG_NONE;
9436 tmp_ctx = talloc_new(p->mem_ctx);
9437 if (!tmp_ctx) {
9438 return WERR_NOMEM;
9441 if (!Printer) {
9442 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9443 OUR_HANDLE(r->in.handle)));
9444 result = WERR_BADFID;
9445 goto done;
9448 /* check to see if the keyname is valid */
9449 if (!strlen(r->in.key_name)) {
9450 result = WERR_INVALID_PARAM;
9451 goto done;
9454 /* Is the handle to a printer or to the server? */
9456 if (Printer->printer_type == SPLHND_SERVER) {
9458 union spoolss_PrinterData data;
9460 result = getprinterdata_printer_server(tmp_ctx,
9461 r->in.value_name,
9462 r->out.type,
9463 &data);
9464 if (!W_ERROR_IS_OK(result)) {
9465 goto done;
9468 result = push_spoolss_PrinterData(tmp_ctx, &blob,
9469 *r->out.type, &data);
9470 if (!W_ERROR_IS_OK(result)) {
9471 goto done;
9474 *r->out.needed = blob.length;
9476 if (r->in.offered >= *r->out.needed) {
9477 memcpy(r->out.data, blob.data, blob.length);
9480 result = WERR_OK;
9481 goto done;
9484 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9485 result = WERR_BADFID;
9486 goto done;
9488 printer = lp_const_servicename(snum);
9490 result = winreg_printer_binding_handle(tmp_ctx,
9491 get_session_info_system(),
9492 p->msg_ctx,
9493 &b);
9494 if (!W_ERROR_IS_OK(result)) {
9495 goto done;
9498 /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9499 if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9500 strequal(r->in.value_name, "ChangeId")) {
9501 *r->out.type = REG_DWORD;
9502 *r->out.needed = 4;
9503 if (r->in.offered >= *r->out.needed) {
9504 uint32_t changeid = 0;
9506 result = winreg_printer_get_changeid(tmp_ctx, b,
9507 printer,
9508 &changeid);
9509 if (!W_ERROR_IS_OK(result)) {
9510 goto done;
9513 SIVAL(r->out.data, 0, changeid);
9514 result = WERR_OK;
9516 goto done;
9519 result = winreg_get_printer_dataex(tmp_ctx, b,
9520 printer,
9521 r->in.key_name,
9522 r->in.value_name,
9523 &val_type,
9524 &val_data,
9525 &val_size);
9526 if (!W_ERROR_IS_OK(result)) {
9527 goto done;
9530 *r->out.needed = val_size;
9531 *r->out.type = val_type;
9533 if (r->in.offered >= *r->out.needed) {
9534 memcpy(r->out.data, val_data, val_size);
9537 done:
9538 /* NOTE: do not replace type when returning WERR_MORE_DATA */
9540 if (W_ERROR_IS_OK(result)) {
9541 result = SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9544 talloc_free(tmp_ctx);
9545 return result;
9548 /****************************************************************
9549 _spoolss_SetPrinterDataEx
9550 ****************************************************************/
9552 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9553 struct spoolss_SetPrinterDataEx *r)
9555 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9556 int snum = 0;
9557 WERROR result = WERR_OK;
9558 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9559 char *oid_string;
9560 struct dcerpc_binding_handle *b;
9561 TALLOC_CTX *tmp_ctx;
9563 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9565 /* From MSDN documentation of SetPrinterDataEx: pass request to
9566 SetPrinterData if key is "PrinterDriverData" */
9568 if (!Printer) {
9569 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9570 OUR_HANDLE(r->in.handle)));
9571 return WERR_BADFID;
9574 if (Printer->printer_type == SPLHND_SERVER) {
9575 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9576 "Not implemented for server handles yet\n"));
9577 return WERR_INVALID_PARAM;
9580 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9581 return WERR_BADFID;
9585 * Access check : NT returns "access denied" if you make a
9586 * SetPrinterData call without the necessary privildge.
9587 * we were originally returning OK if nothing changed
9588 * which made Win2k issue **a lot** of SetPrinterData
9589 * when connecting to a printer --jerry
9592 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9593 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9594 "change denied by handle access permissions\n"));
9595 return WERR_ACCESS_DENIED;
9598 tmp_ctx = talloc_new(p->mem_ctx);
9599 if (!tmp_ctx) {
9600 return WERR_NOMEM;
9603 result = winreg_printer_binding_handle(tmp_ctx,
9604 get_session_info_system(),
9605 p->msg_ctx,
9606 &b);
9607 if (!W_ERROR_IS_OK(result)) {
9608 goto done;
9611 result = winreg_get_printer(tmp_ctx, b,
9612 lp_servicename(talloc_tos(), snum),
9613 &pinfo2);
9614 if (!W_ERROR_IS_OK(result)) {
9615 goto done;
9618 /* check for OID in valuename */
9620 oid_string = strchr(r->in.value_name, ',');
9621 if (oid_string) {
9622 *oid_string = '\0';
9623 oid_string++;
9626 /* save the registry data */
9628 result = winreg_set_printer_dataex(tmp_ctx, b,
9629 pinfo2->sharename,
9630 r->in.key_name,
9631 r->in.value_name,
9632 r->in.type,
9633 r->in.data,
9634 r->in.offered);
9636 if (W_ERROR_IS_OK(result)) {
9637 /* save the OID if one was specified */
9638 if (oid_string) {
9639 char *str = talloc_asprintf(tmp_ctx, "%s\\%s",
9640 r->in.key_name, SPOOL_OID_KEY);
9641 if (!str) {
9642 result = WERR_NOMEM;
9643 goto done;
9647 * I'm not checking the status here on purpose. Don't know
9648 * if this is right, but I'm returning the status from the
9649 * previous set_printer_dataex() call. I have no idea if
9650 * this is right. --jerry
9652 winreg_set_printer_dataex(tmp_ctx, b,
9653 pinfo2->sharename,
9654 str,
9655 r->in.value_name,
9656 REG_SZ,
9657 (uint8_t *) oid_string,
9658 strlen(oid_string) + 1);
9661 result = winreg_printer_update_changeid(tmp_ctx, b,
9662 lp_const_servicename(snum));
9666 done:
9667 talloc_free(tmp_ctx);
9668 return result;
9671 /****************************************************************
9672 _spoolss_DeletePrinterDataEx
9673 ****************************************************************/
9675 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9676 struct spoolss_DeletePrinterDataEx *r)
9678 const char *printer;
9679 int snum=0;
9680 WERROR status = WERR_OK;
9681 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9683 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9685 if (!Printer) {
9686 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9687 "Invalid handle (%s:%u:%u).\n",
9688 OUR_HANDLE(r->in.handle)));
9689 return WERR_BADFID;
9692 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9693 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9694 "printer properties change denied by handle\n"));
9695 return WERR_ACCESS_DENIED;
9698 if (!r->in.value_name || !r->in.key_name) {
9699 return WERR_NOMEM;
9702 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9703 return WERR_BADFID;
9705 printer = lp_const_servicename(snum);
9707 status = winreg_delete_printer_dataex_internal(p->mem_ctx,
9708 get_session_info_system(),
9709 p->msg_ctx,
9710 printer,
9711 r->in.key_name,
9712 r->in.value_name);
9713 if (W_ERROR_IS_OK(status)) {
9714 status = winreg_printer_update_changeid_internal(p->mem_ctx,
9715 get_session_info_system(),
9716 p->msg_ctx,
9717 printer);
9720 return status;
9723 /****************************************************************
9724 _spoolss_EnumPrinterKey
9725 ****************************************************************/
9727 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9728 struct spoolss_EnumPrinterKey *r)
9730 uint32_t num_keys;
9731 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9732 int snum = 0;
9733 WERROR result = WERR_BADFILE;
9734 const char **array = NULL;
9735 DATA_BLOB blob;
9737 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9739 if (!Printer) {
9740 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9741 OUR_HANDLE(r->in.handle)));
9742 return WERR_BADFID;
9745 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9746 return WERR_BADFID;
9749 result = winreg_enum_printer_key_internal(p->mem_ctx,
9750 get_session_info_system(),
9751 p->msg_ctx,
9752 lp_const_servicename(snum),
9753 r->in.key_name,
9754 &num_keys,
9755 &array);
9756 if (!W_ERROR_IS_OK(result)) {
9757 goto done;
9760 if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9761 result = WERR_NOMEM;
9762 goto done;
9765 *r->out._ndr_size = r->in.offered / 2;
9766 *r->out.needed = blob.length;
9768 if (r->in.offered < *r->out.needed) {
9769 result = WERR_MORE_DATA;
9770 } else {
9771 result = WERR_OK;
9772 r->out.key_buffer->string_array = array;
9775 done:
9776 if (!W_ERROR_IS_OK(result)) {
9777 TALLOC_FREE(array);
9778 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9779 *r->out.needed = 0;
9783 return result;
9786 /****************************************************************
9787 _spoolss_DeletePrinterKey
9788 ****************************************************************/
9790 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9791 struct spoolss_DeletePrinterKey *r)
9793 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9794 int snum=0;
9795 WERROR status;
9796 const char *printer;
9797 struct dcerpc_binding_handle *b;
9798 TALLOC_CTX *tmp_ctx;
9800 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9802 if (!Printer) {
9803 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9804 OUR_HANDLE(r->in.handle)));
9805 return WERR_BADFID;
9808 /* if keyname == NULL, return error */
9809 if ( !r->in.key_name )
9810 return WERR_INVALID_PARAM;
9812 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9813 return WERR_BADFID;
9816 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9817 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9818 "printer properties change denied by handle\n"));
9819 return WERR_ACCESS_DENIED;
9822 printer = lp_const_servicename(snum);
9824 tmp_ctx = talloc_new(p->mem_ctx);
9825 if (!tmp_ctx) {
9826 return WERR_NOMEM;
9829 status = winreg_printer_binding_handle(tmp_ctx,
9830 get_session_info_system(),
9831 p->msg_ctx,
9832 &b);
9833 if (!W_ERROR_IS_OK(status)) {
9834 goto done;
9837 /* delete the key and all subkeys */
9838 status = winreg_delete_printer_key(tmp_ctx, b,
9839 printer,
9840 r->in.key_name);
9841 if (W_ERROR_IS_OK(status)) {
9842 status = winreg_printer_update_changeid(tmp_ctx, b,
9843 printer);
9846 done:
9847 talloc_free(tmp_ctx);
9848 return status;
9851 /****************************************************************
9852 _spoolss_EnumPrinterDataEx
9853 ****************************************************************/
9855 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
9856 struct spoolss_EnumPrinterDataEx *r)
9858 uint32_t count = 0;
9859 struct spoolss_PrinterEnumValues *info = NULL;
9860 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9861 int snum;
9862 WERROR result;
9864 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9866 *r->out.count = 0;
9867 *r->out.needed = 0;
9868 *r->out.info = NULL;
9870 if (!Printer) {
9871 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9872 OUR_HANDLE(r->in.handle)));
9873 return WERR_BADFID;
9877 * first check for a keyname of NULL or "". Win2k seems to send
9878 * this a lot and we should send back WERR_INVALID_PARAM
9879 * no need to spend time looking up the printer in this case.
9880 * --jerry
9883 if (!strlen(r->in.key_name)) {
9884 result = WERR_INVALID_PARAM;
9885 goto done;
9888 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9889 return WERR_BADFID;
9892 /* now look for a match on the key name */
9893 result = winreg_enum_printer_dataex_internal(p->mem_ctx,
9894 get_session_info_system(),
9895 p->msg_ctx,
9896 lp_const_servicename(snum),
9897 r->in.key_name,
9898 &count,
9899 &info);
9900 if (!W_ERROR_IS_OK(result)) {
9901 goto done;
9904 #if 0 /* FIXME - gd */
9905 /* housekeeping information in the reply */
9907 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9908 * the hand marshalled container size is a multiple
9909 * of 4 bytes for RPC alignment.
9912 if (needed % 4) {
9913 needed += 4-(needed % 4);
9915 #endif
9916 *r->out.count = count;
9917 *r->out.info = info;
9919 done:
9920 if (!W_ERROR_IS_OK(result)) {
9921 return result;
9924 *r->out.needed = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9925 spoolss_EnumPrinterDataEx,
9926 *r->out.info,
9927 *r->out.count);
9928 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9929 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9931 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9934 /****************************************************************************
9935 ****************************************************************************/
9937 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9938 const char *servername,
9939 const char *environment,
9940 struct spoolss_PrintProcessorDirectoryInfo1 *r)
9942 WERROR werr;
9943 char *path = NULL;
9945 werr = compose_spoolss_server_path(mem_ctx,
9946 servername,
9947 environment,
9948 SPOOLSS_PRTPROCS_PATH,
9949 &path);
9950 if (!W_ERROR_IS_OK(werr)) {
9951 return werr;
9954 DEBUG(4,("print processor directory: [%s]\n", path));
9956 r->directory_name = path;
9958 return WERR_OK;
9961 /****************************************************************
9962 _spoolss_GetPrintProcessorDirectory
9963 ****************************************************************/
9965 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
9966 struct spoolss_GetPrintProcessorDirectory *r)
9968 WERROR result;
9969 char *prnproc_share = NULL;
9970 bool prnproc_share_exists = false;
9971 int snum;
9973 /* that's an [in out] buffer */
9975 if (!r->in.buffer && (r->in.offered != 0)) {
9976 return WERR_INVALID_PARAM;
9979 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9980 r->in.level));
9982 *r->out.needed = 0;
9984 /* r->in.level is ignored */
9986 /* We always should reply with a local print processor directory so that
9987 * users are not forced to have a [prnproc$] share on the Samba spoolss
9988 * server, if users decide to do so, lets announce it though - Guenther */
9990 snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
9991 if (!prnproc_share) {
9992 return WERR_NOMEM;
9994 if (snum != -1) {
9995 prnproc_share_exists = true;
9998 result = getprintprocessordirectory_level_1(p->mem_ctx,
9999 prnproc_share_exists ? r->in.server : NULL,
10000 r->in.environment,
10001 &r->out.info->info1);
10002 if (!W_ERROR_IS_OK(result)) {
10003 TALLOC_FREE(r->out.info);
10004 return result;
10007 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
10008 r->out.info, r->in.level);
10009 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
10011 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
10014 /*******************************************************************
10015 ********************************************************************/
10017 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
10018 const char *dllname)
10020 enum ndr_err_code ndr_err;
10021 struct spoolss_MonitorUi ui;
10023 ui.dll_name = dllname;
10025 ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
10026 (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
10027 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10028 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
10030 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10033 /*******************************************************************
10034 Streams the monitor UI DLL name in UNICODE
10035 *******************************************************************/
10037 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
10038 struct security_token *token, DATA_BLOB *in,
10039 DATA_BLOB *out, uint32_t *needed)
10041 const char *dllname = "tcpmonui.dll";
10043 *needed = (strlen(dllname)+1) * 2;
10045 if (out->length < *needed) {
10046 return WERR_INSUFFICIENT_BUFFER;
10049 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10050 return WERR_NOMEM;
10053 return WERR_OK;
10056 /*******************************************************************
10057 ********************************************************************/
10059 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
10060 struct spoolss_PortData1 *port1,
10061 const DATA_BLOB *buf)
10063 enum ndr_err_code ndr_err;
10064 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
10065 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
10066 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10067 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
10069 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10072 /*******************************************************************
10073 ********************************************************************/
10075 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
10076 struct spoolss_PortData2 *port2,
10077 const DATA_BLOB *buf)
10079 enum ndr_err_code ndr_err;
10080 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
10081 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
10082 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10083 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
10085 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10088 /*******************************************************************
10089 Create a new TCP/IP port
10090 *******************************************************************/
10092 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
10093 struct security_token *token, DATA_BLOB *in,
10094 DATA_BLOB *out, uint32_t *needed)
10096 struct spoolss_PortData1 port1;
10097 struct spoolss_PortData2 port2;
10098 char *device_uri = NULL;
10099 uint32_t version;
10101 const char *portname;
10102 const char *hostaddress;
10103 const char *queue;
10104 uint32_t port_number;
10105 uint32_t protocol;
10107 /* peek for spoolss_PortData version */
10109 if (!in || (in->length < (128 + 4))) {
10110 return WERR_GENERAL_FAILURE;
10113 version = IVAL(in->data, 128);
10115 switch (version) {
10116 case 1:
10117 ZERO_STRUCT(port1);
10119 if (!pull_port_data_1(mem_ctx, &port1, in)) {
10120 return WERR_NOMEM;
10123 portname = port1.portname;
10124 hostaddress = port1.hostaddress;
10125 queue = port1.queue;
10126 protocol = port1.protocol;
10127 port_number = port1.port_number;
10129 break;
10130 case 2:
10131 ZERO_STRUCT(port2);
10133 if (!pull_port_data_2(mem_ctx, &port2, in)) {
10134 return WERR_NOMEM;
10137 portname = port2.portname;
10138 hostaddress = port2.hostaddress;
10139 queue = port2.queue;
10140 protocol = port2.protocol;
10141 port_number = port2.port_number;
10143 break;
10144 default:
10145 DEBUG(1,("xcvtcp_addport: "
10146 "unknown version of port_data: %d\n", version));
10147 return WERR_UNKNOWN_PORT;
10150 /* create the device URI and call the add_port_hook() */
10152 switch (protocol) {
10153 case PROTOCOL_RAWTCP_TYPE:
10154 device_uri = talloc_asprintf(mem_ctx,
10155 "socket://%s:%d/", hostaddress,
10156 port_number);
10157 break;
10159 case PROTOCOL_LPR_TYPE:
10160 device_uri = talloc_asprintf(mem_ctx,
10161 "lpr://%s/%s", hostaddress, queue );
10162 break;
10164 default:
10165 return WERR_UNKNOWN_PORT;
10168 if (!device_uri) {
10169 return WERR_NOMEM;
10172 return add_port_hook(mem_ctx, token, portname, device_uri);
10175 /*******************************************************************
10176 *******************************************************************/
10178 struct xcv_api_table xcvtcp_cmds[] = {
10179 { "MonitorUI", xcvtcp_monitorui },
10180 { "AddPort", xcvtcp_addport},
10181 { NULL, NULL }
10184 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
10185 struct security_token *token, const char *command,
10186 DATA_BLOB *inbuf,
10187 DATA_BLOB *outbuf,
10188 uint32_t *needed )
10190 int i;
10192 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
10194 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
10195 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
10196 return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10199 return WERR_BADFUNC;
10202 /*******************************************************************
10203 *******************************************************************/
10204 #if 0 /* don't support management using the "Local Port" monitor */
10206 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
10207 struct security_token *token, DATA_BLOB *in,
10208 DATA_BLOB *out, uint32_t *needed)
10210 const char *dllname = "localui.dll";
10212 *needed = (strlen(dllname)+1) * 2;
10214 if (out->length < *needed) {
10215 return WERR_INSUFFICIENT_BUFFER;
10218 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10219 return WERR_NOMEM;
10222 return WERR_OK;
10225 /*******************************************************************
10226 *******************************************************************/
10228 struct xcv_api_table xcvlocal_cmds[] = {
10229 { "MonitorUI", xcvlocal_monitorui },
10230 { NULL, NULL }
10232 #else
10233 struct xcv_api_table xcvlocal_cmds[] = {
10234 { NULL, NULL }
10236 #endif
10240 /*******************************************************************
10241 *******************************************************************/
10243 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
10244 struct security_token *token, const char *command,
10245 DATA_BLOB *inbuf, DATA_BLOB *outbuf,
10246 uint32_t *needed)
10248 int i;
10250 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10252 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10253 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10254 return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10256 return WERR_BADFUNC;
10259 /****************************************************************
10260 _spoolss_XcvData
10261 ****************************************************************/
10263 WERROR _spoolss_XcvData(struct pipes_struct *p,
10264 struct spoolss_XcvData *r)
10266 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10267 DATA_BLOB out_data = data_blob_null;
10268 WERROR werror;
10270 if (!Printer) {
10271 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10272 OUR_HANDLE(r->in.handle)));
10273 return WERR_BADFID;
10276 /* Has to be a handle to the TCP/IP port monitor */
10278 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10279 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10280 return WERR_BADFID;
10283 /* requires administrative access to the server */
10285 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10286 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10287 return WERR_ACCESS_DENIED;
10290 /* Allocate the outgoing buffer */
10292 if (r->in.out_data_size) {
10293 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10294 if (out_data.data == NULL) {
10295 return WERR_NOMEM;
10299 switch ( Printer->printer_type ) {
10300 case SPLHND_PORTMON_TCP:
10301 werror = process_xcvtcp_command(p->mem_ctx,
10302 p->session_info->security_token,
10303 r->in.function_name,
10304 &r->in.in_data, &out_data,
10305 r->out.needed);
10306 break;
10307 case SPLHND_PORTMON_LOCAL:
10308 werror = process_xcvlocal_command(p->mem_ctx,
10309 p->session_info->security_token,
10310 r->in.function_name,
10311 &r->in.in_data, &out_data,
10312 r->out.needed);
10313 break;
10314 default:
10315 werror = WERR_INVALID_PRINT_MONITOR;
10318 if (!W_ERROR_IS_OK(werror)) {
10319 return werror;
10322 *r->out.status_code = 0;
10324 if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10325 memcpy(r->out.out_data, out_data.data,
10326 MIN(r->in.out_data_size, out_data.length));
10329 return WERR_OK;
10332 /****************************************************************
10333 _spoolss_AddPrintProcessor
10334 ****************************************************************/
10336 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10337 struct spoolss_AddPrintProcessor *r)
10339 /* for now, just indicate success and ignore the add. We'll
10340 automatically set the winprint processor for printer
10341 entries later. Used to debug the LexMark Optra S 1855 PCL
10342 driver --jerry */
10344 return WERR_OK;
10347 /****************************************************************
10348 _spoolss_AddPort
10349 ****************************************************************/
10351 WERROR _spoolss_AddPort(struct pipes_struct *p,
10352 struct spoolss_AddPort *r)
10354 /* do what w2k3 does */
10356 return WERR_NOT_SUPPORTED;
10359 /****************************************************************
10360 _spoolss_GetPrinterDriver
10361 ****************************************************************/
10363 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10364 struct spoolss_GetPrinterDriver *r)
10366 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10367 return WERR_NOT_SUPPORTED;
10370 /****************************************************************
10371 _spoolss_ReadPrinter
10372 ****************************************************************/
10374 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10375 struct spoolss_ReadPrinter *r)
10377 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10378 return WERR_NOT_SUPPORTED;
10381 /****************************************************************
10382 _spoolss_WaitForPrinterChange
10383 ****************************************************************/
10385 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10386 struct spoolss_WaitForPrinterChange *r)
10388 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10389 return WERR_NOT_SUPPORTED;
10392 /****************************************************************
10393 _spoolss_ConfigurePort
10394 ****************************************************************/
10396 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10397 struct spoolss_ConfigurePort *r)
10399 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10400 return WERR_NOT_SUPPORTED;
10403 /****************************************************************
10404 _spoolss_DeletePort
10405 ****************************************************************/
10407 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10408 struct spoolss_DeletePort *r)
10410 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10411 return WERR_NOT_SUPPORTED;
10414 /****************************************************************
10415 _spoolss_CreatePrinterIC
10416 ****************************************************************/
10418 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10419 struct spoolss_CreatePrinterIC *r)
10421 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10422 return WERR_NOT_SUPPORTED;
10425 /****************************************************************
10426 _spoolss_PlayGDIScriptOnPrinterIC
10427 ****************************************************************/
10429 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10430 struct spoolss_PlayGDIScriptOnPrinterIC *r)
10432 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10433 return WERR_NOT_SUPPORTED;
10436 /****************************************************************
10437 _spoolss_DeletePrinterIC
10438 ****************************************************************/
10440 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10441 struct spoolss_DeletePrinterIC *r)
10443 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10444 return WERR_NOT_SUPPORTED;
10447 /****************************************************************
10448 _spoolss_AddPrinterConnection
10449 ****************************************************************/
10451 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10452 struct spoolss_AddPrinterConnection *r)
10454 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10455 return WERR_NOT_SUPPORTED;
10458 /****************************************************************
10459 _spoolss_DeletePrinterConnection
10460 ****************************************************************/
10462 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10463 struct spoolss_DeletePrinterConnection *r)
10465 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10466 return WERR_NOT_SUPPORTED;
10469 /****************************************************************
10470 _spoolss_PrinterMessageBox
10471 ****************************************************************/
10473 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10474 struct spoolss_PrinterMessageBox *r)
10476 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10477 return WERR_NOT_SUPPORTED;
10480 /****************************************************************
10481 _spoolss_AddMonitor
10482 ****************************************************************/
10484 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10485 struct spoolss_AddMonitor *r)
10487 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10488 return WERR_NOT_SUPPORTED;
10491 /****************************************************************
10492 _spoolss_DeleteMonitor
10493 ****************************************************************/
10495 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10496 struct spoolss_DeleteMonitor *r)
10498 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10499 return WERR_NOT_SUPPORTED;
10502 /****************************************************************
10503 _spoolss_DeletePrintProcessor
10504 ****************************************************************/
10506 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10507 struct spoolss_DeletePrintProcessor *r)
10509 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10510 return WERR_NOT_SUPPORTED;
10513 /****************************************************************
10514 _spoolss_AddPrintProvidor
10515 ****************************************************************/
10517 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10518 struct spoolss_AddPrintProvidor *r)
10520 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10521 return WERR_NOT_SUPPORTED;
10524 /****************************************************************
10525 _spoolss_DeletePrintProvidor
10526 ****************************************************************/
10528 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10529 struct spoolss_DeletePrintProvidor *r)
10531 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10532 return WERR_NOT_SUPPORTED;
10535 /****************************************************************
10536 _spoolss_FindFirstPrinterChangeNotification
10537 ****************************************************************/
10539 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10540 struct spoolss_FindFirstPrinterChangeNotification *r)
10542 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10543 return WERR_NOT_SUPPORTED;
10546 /****************************************************************
10547 _spoolss_FindNextPrinterChangeNotification
10548 ****************************************************************/
10550 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10551 struct spoolss_FindNextPrinterChangeNotification *r)
10553 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10554 return WERR_NOT_SUPPORTED;
10557 /****************************************************************
10558 _spoolss_RouterFindFirstPrinterChangeNotificationOld
10559 ****************************************************************/
10561 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10562 struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10564 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10565 return WERR_NOT_SUPPORTED;
10568 /****************************************************************
10569 _spoolss_ReplyOpenPrinter
10570 ****************************************************************/
10572 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10573 struct spoolss_ReplyOpenPrinter *r)
10575 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10576 return WERR_NOT_SUPPORTED;
10579 /****************************************************************
10580 _spoolss_RouterReplyPrinter
10581 ****************************************************************/
10583 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10584 struct spoolss_RouterReplyPrinter *r)
10586 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10587 return WERR_NOT_SUPPORTED;
10590 /****************************************************************
10591 _spoolss_ReplyClosePrinter
10592 ****************************************************************/
10594 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10595 struct spoolss_ReplyClosePrinter *r)
10597 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10598 return WERR_NOT_SUPPORTED;
10601 /****************************************************************
10602 _spoolss_AddPortEx
10603 ****************************************************************/
10605 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10606 struct spoolss_AddPortEx *r)
10608 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10609 return WERR_NOT_SUPPORTED;
10612 /****************************************************************
10613 _spoolss_RouterFindFirstPrinterChangeNotification
10614 ****************************************************************/
10616 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10617 struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10619 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10620 return WERR_NOT_SUPPORTED;
10623 /****************************************************************
10624 _spoolss_SpoolerInit
10625 ****************************************************************/
10627 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10628 struct spoolss_SpoolerInit *r)
10630 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10631 return WERR_NOT_SUPPORTED;
10634 /****************************************************************
10635 _spoolss_ResetPrinterEx
10636 ****************************************************************/
10638 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10639 struct spoolss_ResetPrinterEx *r)
10641 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10642 return WERR_NOT_SUPPORTED;
10645 /****************************************************************
10646 _spoolss_RouterReplyPrinterEx
10647 ****************************************************************/
10649 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10650 struct spoolss_RouterReplyPrinterEx *r)
10652 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10653 return WERR_NOT_SUPPORTED;
10656 /****************************************************************
10657 _spoolss_44
10658 ****************************************************************/
10660 WERROR _spoolss_44(struct pipes_struct *p,
10661 struct spoolss_44 *r)
10663 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10664 return WERR_NOT_SUPPORTED;
10667 /****************************************************************
10668 _spoolss_SetPort
10669 ****************************************************************/
10671 WERROR _spoolss_SetPort(struct pipes_struct *p,
10672 struct spoolss_SetPort *r)
10674 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10675 return WERR_NOT_SUPPORTED;
10678 /****************************************************************
10679 _spoolss_4a
10680 ****************************************************************/
10682 WERROR _spoolss_4a(struct pipes_struct *p,
10683 struct spoolss_4a *r)
10685 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10686 return WERR_NOT_SUPPORTED;
10689 /****************************************************************
10690 _spoolss_4b
10691 ****************************************************************/
10693 WERROR _spoolss_4b(struct pipes_struct *p,
10694 struct spoolss_4b *r)
10696 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10697 return WERR_NOT_SUPPORTED;
10700 /****************************************************************
10701 _spoolss_4c
10702 ****************************************************************/
10704 WERROR _spoolss_4c(struct pipes_struct *p,
10705 struct spoolss_4c *r)
10707 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10708 return WERR_NOT_SUPPORTED;
10711 /****************************************************************
10712 _spoolss_53
10713 ****************************************************************/
10715 WERROR _spoolss_53(struct pipes_struct *p,
10716 struct spoolss_53 *r)
10718 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10719 return WERR_NOT_SUPPORTED;
10722 /****************************************************************
10723 _spoolss_AddPerMachineConnection
10724 ****************************************************************/
10726 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
10727 struct spoolss_AddPerMachineConnection *r)
10729 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10730 return WERR_NOT_SUPPORTED;
10733 /****************************************************************
10734 _spoolss_DeletePerMachineConnection
10735 ****************************************************************/
10737 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
10738 struct spoolss_DeletePerMachineConnection *r)
10740 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10741 return WERR_NOT_SUPPORTED;
10744 /****************************************************************
10745 _spoolss_EnumPerMachineConnections
10746 ****************************************************************/
10748 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
10749 struct spoolss_EnumPerMachineConnections *r)
10751 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10752 return WERR_NOT_SUPPORTED;
10755 /****************************************************************
10756 _spoolss_5a
10757 ****************************************************************/
10759 WERROR _spoolss_5a(struct pipes_struct *p,
10760 struct spoolss_5a *r)
10762 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10763 return WERR_NOT_SUPPORTED;
10766 /****************************************************************
10767 _spoolss_5b
10768 ****************************************************************/
10770 WERROR _spoolss_5b(struct pipes_struct *p,
10771 struct spoolss_5b *r)
10773 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10774 return WERR_NOT_SUPPORTED;
10777 /****************************************************************
10778 _spoolss_5c
10779 ****************************************************************/
10781 WERROR _spoolss_5c(struct pipes_struct *p,
10782 struct spoolss_5c *r)
10784 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10785 return WERR_NOT_SUPPORTED;
10788 /****************************************************************
10789 _spoolss_5d
10790 ****************************************************************/
10792 WERROR _spoolss_5d(struct pipes_struct *p,
10793 struct spoolss_5d *r)
10795 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10796 return WERR_NOT_SUPPORTED;
10799 /****************************************************************
10800 _spoolss_5e
10801 ****************************************************************/
10803 WERROR _spoolss_5e(struct pipes_struct *p,
10804 struct spoolss_5e *r)
10806 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10807 return WERR_NOT_SUPPORTED;
10810 /****************************************************************
10811 _spoolss_5f
10812 ****************************************************************/
10814 WERROR _spoolss_5f(struct pipes_struct *p,
10815 struct spoolss_5f *r)
10817 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10818 return WERR_NOT_SUPPORTED;
10821 /****************************************************************
10822 _spoolss_60
10823 ****************************************************************/
10825 WERROR _spoolss_60(struct pipes_struct *p,
10826 struct spoolss_60 *r)
10828 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10829 return WERR_NOT_SUPPORTED;
10832 /****************************************************************
10833 _spoolss_61
10834 ****************************************************************/
10836 WERROR _spoolss_61(struct pipes_struct *p,
10837 struct spoolss_61 *r)
10839 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10840 return WERR_NOT_SUPPORTED;
10843 /****************************************************************
10844 _spoolss_62
10845 ****************************************************************/
10847 WERROR _spoolss_62(struct pipes_struct *p,
10848 struct spoolss_62 *r)
10850 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10851 return WERR_NOT_SUPPORTED;
10854 /****************************************************************
10855 _spoolss_63
10856 ****************************************************************/
10858 WERROR _spoolss_63(struct pipes_struct *p,
10859 struct spoolss_63 *r)
10861 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10862 return WERR_NOT_SUPPORTED;
10865 /****************************************************************
10866 _spoolss_64
10867 ****************************************************************/
10869 WERROR _spoolss_64(struct pipes_struct *p,
10870 struct spoolss_64 *r)
10872 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10873 return WERR_NOT_SUPPORTED;
10876 /****************************************************************
10877 _spoolss_65
10878 ****************************************************************/
10880 WERROR _spoolss_65(struct pipes_struct *p,
10881 struct spoolss_65 *r)
10883 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10884 return WERR_NOT_SUPPORTED;
10887 /****************************************************************
10888 _spoolss_GetCorePrinterDrivers
10889 ****************************************************************/
10891 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
10892 struct spoolss_GetCorePrinterDrivers *r)
10894 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10895 return WERR_NOT_SUPPORTED;
10898 /****************************************************************
10899 _spoolss_67
10900 ****************************************************************/
10902 WERROR _spoolss_67(struct pipes_struct *p,
10903 struct spoolss_67 *r)
10905 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10906 return WERR_NOT_SUPPORTED;
10909 /****************************************************************
10910 _spoolss_GetPrinterDriverPackagePath
10911 ****************************************************************/
10913 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
10914 struct spoolss_GetPrinterDriverPackagePath *r)
10916 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10917 return WERR_NOT_SUPPORTED;
10920 /****************************************************************
10921 _spoolss_69
10922 ****************************************************************/
10924 WERROR _spoolss_69(struct pipes_struct *p,
10925 struct spoolss_69 *r)
10927 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10928 return WERR_NOT_SUPPORTED;
10931 /****************************************************************
10932 _spoolss_6a
10933 ****************************************************************/
10935 WERROR _spoolss_6a(struct pipes_struct *p,
10936 struct spoolss_6a *r)
10938 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10939 return WERR_NOT_SUPPORTED;
10942 /****************************************************************
10943 _spoolss_6b
10944 ****************************************************************/
10946 WERROR _spoolss_6b(struct pipes_struct *p,
10947 struct spoolss_6b *r)
10949 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10950 return WERR_NOT_SUPPORTED;
10953 /****************************************************************
10954 _spoolss_6c
10955 ****************************************************************/
10957 WERROR _spoolss_6c(struct pipes_struct *p,
10958 struct spoolss_6c *r)
10960 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10961 return WERR_NOT_SUPPORTED;
10964 /****************************************************************
10965 _spoolss_6d
10966 ****************************************************************/
10968 WERROR _spoolss_6d(struct pipes_struct *p,
10969 struct spoolss_6d *r)
10971 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10972 return WERR_NOT_SUPPORTED;
10975 /****************************************************************
10976 _spoolss_RpcGetJobNamedPropertyValue
10977 ****************************************************************/
10979 WERROR _spoolss_RpcGetJobNamedPropertyValue(struct pipes_struct *p,
10980 struct spoolss_RpcGetJobNamedPropertyValue *r)
10982 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10983 return WERR_NOT_SUPPORTED;
10986 /****************************************************************
10987 _spoolss_RpcSetJobNamedProperty
10988 ****************************************************************/
10990 WERROR _spoolss_RpcSetJobNamedProperty(struct pipes_struct *p,
10991 struct spoolss_RpcSetJobNamedProperty *r)
10993 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10994 return WERR_NOT_SUPPORTED;
10997 /****************************************************************
10998 _spoolss_RpcDeleteJobNamedProperty
10999 ****************************************************************/
11001 WERROR _spoolss_RpcDeleteJobNamedProperty(struct pipes_struct *p,
11002 struct spoolss_RpcDeleteJobNamedProperty *r)
11004 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11005 return WERR_NOT_SUPPORTED;
11008 /****************************************************************
11009 _spoolss_RpcEnumJobNamedProperties
11010 ****************************************************************/
11012 WERROR _spoolss_RpcEnumJobNamedProperties(struct pipes_struct *p,
11013 struct spoolss_RpcEnumJobNamedProperties *r)
11015 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11016 return WERR_NOT_SUPPORTED;