s3-spoolss: Fixed some build warnings.
[Samba/bjacke.git] / source3 / rpc_server / srv_spoolss_nt.c
blobb4f960d0bcea86ad7e365389365fd5ddc123dddc
1 /*
2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6 * Copyright (C) Jean François Micouleau 1998-2000,
7 * Copyright (C) Jeremy Allison 2001-2002,
8 * Copyright (C) Gerald Carter 2000-2004,
9 * Copyright (C) Tim Potter 2001-2002.
10 * Copyright (C) Guenther Deschner 2009-2010.
11 * Copyright (C) Andreas Schneider 2010.
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 3 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, see <http://www.gnu.org/licenses/>.
27 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
28 up, all the errors returned are DOS errors, not NT status codes. */
30 #include "includes.h"
31 #include "nt_printing.h"
32 #include "srv_spoolss_util.h"
33 #include "../librpc/gen_ndr/srv_spoolss.h"
34 #include "../librpc/gen_ndr/cli_spoolss.h"
35 #include "rpc_client/init_spoolss.h"
36 #include "librpc/gen_ndr/messaging.h"
37 #include "librpc/gen_ndr/ndr_security.h"
38 #include "registry.h"
39 #include "registry/reg_objects.h"
40 #include "include/printing.h"
41 #include "secrets.h"
42 #include "../librpc/gen_ndr/netlogon.h"
43 #include "rpc_misc.h"
45 /* macros stolen from s4 spoolss server */
46 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
47 ((info)?ndr_size_##fn(info, level, 0):0)
49 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
50 ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
52 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
53 ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
55 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
57 #undef DBGC_CLASS
58 #define DBGC_CLASS DBGC_RPC_SRV
60 static Printer_entry *printers_list;
62 typedef struct _counter_printer_0 {
63 struct _counter_printer_0 *next;
64 struct _counter_printer_0 *prev;
66 int snum;
67 uint32_t counter;
68 } counter_printer_0;
70 static counter_printer_0 *counter_list;
72 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
73 static uint32_t smb_connections = 0;
76 /* Map generic permissions to printer object specific permissions */
78 const struct standard_mapping printer_std_mapping = {
79 PRINTER_READ,
80 PRINTER_WRITE,
81 PRINTER_EXECUTE,
82 PRINTER_ALL_ACCESS
85 /* Map generic permissions to print server object specific permissions */
87 const struct standard_mapping printserver_std_mapping = {
88 SERVER_READ,
89 SERVER_WRITE,
90 SERVER_EXECUTE,
91 SERVER_ALL_ACCESS
94 /* API table for Xcv Monitor functions */
96 struct xcv_api_table {
97 const char *name;
98 WERROR(*fn) (TALLOC_CTX *mem_ctx, NT_USER_TOKEN *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
101 static void prune_printername_cache(void);
103 /********************************************************************
104 * Canonicalize servername.
105 ********************************************************************/
107 static const char *canon_servername(const char *servername)
109 const char *pservername = servername;
110 while (*pservername == '\\') {
111 pservername++;
113 return pservername;
116 /* translate between internal status numbers and NT status numbers */
117 static int nt_printj_status(int v)
119 switch (v) {
120 case LPQ_QUEUED:
121 return 0;
122 case LPQ_PAUSED:
123 return JOB_STATUS_PAUSED;
124 case LPQ_SPOOLING:
125 return JOB_STATUS_SPOOLING;
126 case LPQ_PRINTING:
127 return JOB_STATUS_PRINTING;
128 case LPQ_ERROR:
129 return JOB_STATUS_ERROR;
130 case LPQ_DELETING:
131 return JOB_STATUS_DELETING;
132 case LPQ_OFFLINE:
133 return JOB_STATUS_OFFLINE;
134 case LPQ_PAPEROUT:
135 return JOB_STATUS_PAPEROUT;
136 case LPQ_PRINTED:
137 return JOB_STATUS_PRINTED;
138 case LPQ_DELETED:
139 return JOB_STATUS_DELETED;
140 case LPQ_BLOCKED:
141 return JOB_STATUS_BLOCKED_DEVQ;
142 case LPQ_USER_INTERVENTION:
143 return JOB_STATUS_USER_INTERVENTION;
145 return 0;
148 static int nt_printq_status(int v)
150 switch (v) {
151 case LPQ_PAUSED:
152 return PRINTER_STATUS_PAUSED;
153 case LPQ_QUEUED:
154 case LPQ_SPOOLING:
155 case LPQ_PRINTING:
156 return 0;
158 return 0;
161 /***************************************************************************
162 Disconnect from the client
163 ****************************************************************************/
165 static void srv_spoolss_replycloseprinter(
166 int snum, struct policy_handle *handle,
167 struct messaging_context *msg_ctx)
169 WERROR result;
170 NTSTATUS status;
173 * Tell the specific printing tdb we no longer want messages for this printer
174 * by deregistering our PID.
177 if (!print_notify_deregister_pid(snum))
178 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
180 /* weird if the test succeeds !!! */
181 if (smb_connections==0) {
182 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
183 return;
186 status = rpccli_spoolss_ReplyClosePrinter(notify_cli_pipe, talloc_tos(),
187 handle,
188 &result);
189 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
190 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
191 win_errstr(result)));
193 /* if it's the last connection, deconnect the IPC$ share */
194 if (smb_connections==1) {
196 cli_shutdown( rpc_pipe_np_smb_conn(notify_cli_pipe) );
198 * The above call shuts down the pipe also.
200 notify_cli_pipe = NULL;
202 if (msg_ctx != NULL) {
203 messaging_deregister(msg_ctx, MSG_PRINTER_NOTIFY2,
204 NULL);
207 * Tell the serverid.tdb we're no longer
208 * interested in printer notify messages.
211 serverid_register_msg_flags(
212 messaging_server_id(msg_ctx),
213 false, FLAG_MSG_PRINT_NOTIFY);
217 smb_connections--;
220 /****************************************************************************
221 Functions to free a printer entry datastruct.
222 ****************************************************************************/
224 static int printer_entry_destructor(Printer_entry *Printer)
226 if (Printer->notify.client_connected == true) {
227 int snum = -1;
229 if ( Printer->printer_type == SPLHND_SERVER) {
230 snum = -1;
231 srv_spoolss_replycloseprinter(
232 snum, &Printer->notify.client_hnd,
233 Printer->notify.msg_ctx);
234 } else if (Printer->printer_type == SPLHND_PRINTER) {
235 snum = print_queue_snum(Printer->sharename);
236 if (snum != -1)
237 srv_spoolss_replycloseprinter(
238 snum, &Printer->notify.client_hnd,
239 Printer->notify.msg_ctx);
243 Printer->notify.flags=0;
244 Printer->notify.options=0;
245 Printer->notify.localmachine[0]='\0';
246 Printer->notify.printerlocal=0;
247 TALLOC_FREE(Printer->notify.option);
248 Printer->notify.client_connected = false;
250 TALLOC_FREE(Printer->devmode);
252 /* Remove from the internal list. */
253 DLIST_REMOVE(printers_list, Printer);
254 return 0;
257 /****************************************************************************
258 find printer index by handle
259 ****************************************************************************/
261 static Printer_entry *find_printer_index_by_hnd(struct pipes_struct *p,
262 struct policy_handle *hnd)
264 Printer_entry *find_printer = NULL;
266 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
267 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
268 return NULL;
271 return find_printer;
274 /****************************************************************************
275 Close printer index by handle.
276 ****************************************************************************/
278 static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
280 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
282 if (!Printer) {
283 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
284 OUR_HANDLE(hnd)));
285 return false;
288 close_policy_hnd(p, hnd);
290 return true;
293 /****************************************************************************
294 Delete a printer given a handle.
295 ****************************************************************************/
297 static WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token,
298 const char *sharename,
299 struct messaging_context *msg_ctx)
301 char *cmd = lp_deleteprinter_cmd();
302 char *command = NULL;
303 int ret;
304 SE_PRIV se_printop = SE_PRINT_OPERATOR;
305 bool is_print_op = false;
307 /* can't fail if we don't try */
309 if ( !*cmd )
310 return WERR_OK;
312 command = talloc_asprintf(ctx,
313 "%s \"%s\"",
314 cmd, sharename);
315 if (!command) {
316 return WERR_NOMEM;
318 if ( token )
319 is_print_op = user_has_privileges( token, &se_printop );
321 DEBUG(10,("Running [%s]\n", command));
323 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
325 if ( is_print_op )
326 become_root();
328 if ( (ret = smbrun(command, NULL)) == 0 ) {
329 /* Tell everyone we updated smb.conf. */
330 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
333 if ( is_print_op )
334 unbecome_root();
336 /********** END SePrintOperatorPrivlege BLOCK **********/
338 DEBUGADD(10,("returned [%d]\n", ret));
340 TALLOC_FREE(command);
342 if (ret != 0)
343 return WERR_BADFID; /* What to return here? */
345 /* go ahead and re-read the services immediately */
346 become_root();
347 reload_services(msg_ctx, -1, false);
348 unbecome_root();
350 if ( lp_servicenumber( sharename ) > 0 )
351 return WERR_ACCESS_DENIED;
353 return WERR_OK;
356 /****************************************************************************
357 Delete a printer given a handle.
358 ****************************************************************************/
360 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
362 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
363 WERROR result;
365 if (!Printer) {
366 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
367 OUR_HANDLE(hnd)));
368 return WERR_BADFID;
372 * It turns out that Windows allows delete printer on a handle
373 * opened by an admin user, then used on a pipe handle created
374 * by an anonymous user..... but they're working on security.... riiight !
375 * JRA.
378 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
379 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
380 return WERR_ACCESS_DENIED;
383 /* this does not need a become root since the access check has been
384 done on the handle already */
386 result = winreg_delete_printer_key(p->mem_ctx, p->server_info,
387 p->msg_ctx, Printer->sharename, "");
388 if (!W_ERROR_IS_OK(result)) {
389 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
390 return WERR_BADFID;
393 result = delete_printer_hook(p->mem_ctx, p->server_info->ptok,
394 Printer->sharename, p->msg_ctx);
395 if (!W_ERROR_IS_OK(result)) {
396 return result;
398 prune_printername_cache();
399 return WERR_OK;
402 /****************************************************************************
403 Return the snum of a printer corresponding to an handle.
404 ****************************************************************************/
406 static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
407 int *number, struct share_params **params)
409 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
411 if (!Printer) {
412 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
413 OUR_HANDLE(hnd)));
414 return false;
417 switch (Printer->printer_type) {
418 case SPLHND_PRINTER:
419 DEBUG(4,("short name:%s\n", Printer->sharename));
420 *number = print_queue_snum(Printer->sharename);
421 return (*number != -1);
422 case SPLHND_SERVER:
423 return false;
424 default:
425 return false;
429 /****************************************************************************
430 Set printer handle type.
431 Check if it's \\server or \\server\printer
432 ****************************************************************************/
434 static bool set_printer_hnd_printertype(Printer_entry *Printer, const char *handlename)
436 DEBUG(3,("Setting printer type=%s\n", handlename));
438 if ( strlen(handlename) < 3 ) {
439 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
440 return false;
443 /* it's a print server */
444 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
445 DEBUGADD(4,("Printer is a print server\n"));
446 Printer->printer_type = SPLHND_SERVER;
448 /* it's a printer (set_printer_hnd_name() will handle port monitors */
449 else {
450 DEBUGADD(4,("Printer is a printer\n"));
451 Printer->printer_type = SPLHND_PRINTER;
454 return true;
457 static void prune_printername_cache_fn(const char *key, const char *value,
458 time_t timeout, void *private_data)
460 gencache_del(key);
463 static void prune_printername_cache(void)
465 gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
468 /****************************************************************************
469 Set printer handle name.. Accept names like \\server, \\server\printer,
470 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
471 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
472 XcvDataPort() interface.
473 ****************************************************************************/
475 static bool set_printer_hnd_name(TALLOC_CTX *mem_ctx,
476 struct auth_serversupplied_info *server_info,
477 struct messaging_context *msg_ctx,
478 Printer_entry *Printer,
479 const char *handlename)
481 int snum;
482 int n_services=lp_numservices();
483 char *aprinter;
484 const char *printername;
485 const char *servername = NULL;
486 fstring sname;
487 bool found = false;
488 struct spoolss_PrinterInfo2 *info2 = NULL;
489 WERROR result;
492 * Hopefully nobody names his printers like this. Maybe \ or ,
493 * are illegal in printer names even?
495 const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
496 char *cache_key;
497 char *tmp;
499 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
500 (unsigned long)strlen(handlename)));
502 aprinter = CONST_DISCARD(char *, handlename);
503 if ( *handlename == '\\' ) {
504 servername = canon_servername(handlename);
505 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
506 *aprinter = '\0';
507 aprinter++;
509 if (!is_myname_or_ipaddr(servername)) {
510 return false;
513 fstrcpy(Printer->servername, servername);
516 if (Printer->printer_type == SPLHND_SERVER) {
517 return true;
520 if (Printer->printer_type != SPLHND_PRINTER) {
521 return false;
524 DEBUGADD(5, ("searching for [%s]\n", aprinter));
526 /* check for the Port Monitor Interface */
527 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
528 Printer->printer_type = SPLHND_PORTMON_TCP;
529 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
530 found = true;
532 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
533 Printer->printer_type = SPLHND_PORTMON_LOCAL;
534 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
535 found = true;
539 * With hundreds of printers, the "for" loop iterating all
540 * shares can be quite expensive, as it is done on every
541 * OpenPrinter. The loop maps "aprinter" to "sname", the
542 * result of which we cache in gencache.
545 cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s",
546 aprinter);
547 if ((cache_key != NULL) && gencache_get(cache_key, &tmp, NULL)) {
549 found = (strcmp(tmp, printer_not_found) != 0);
550 if (!found) {
551 DEBUG(4, ("Printer %s not found\n", aprinter));
552 SAFE_FREE(tmp);
553 return false;
555 fstrcpy(sname, tmp);
556 SAFE_FREE(tmp);
559 /* Search all sharenames first as this is easier than pulling
560 the printer_info_2 off of disk. Don't use find_service() since
561 that calls out to map_username() */
563 /* do another loop to look for printernames */
564 for (snum = 0; !found && snum < n_services; snum++) {
565 const char *printer = lp_const_servicename(snum);
567 /* no point going on if this is not a printer */
568 if (!(lp_snum_ok(snum) && lp_print_ok(snum))) {
569 continue;
572 /* ignore [printers] share */
573 if (strequal(printer, "printers")) {
574 continue;
577 fstrcpy(sname, printer);
578 if (strequal(aprinter, printer)) {
579 found = true;
580 break;
583 /* no point looking up the printer object if
584 we aren't allowing printername != sharename */
585 if (lp_force_printername(snum)) {
586 continue;
589 result = winreg_get_printer(mem_ctx,
590 server_info,
591 msg_ctx,
592 servername,
593 sname,
594 &info2);
595 if ( !W_ERROR_IS_OK(result) ) {
596 DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
597 sname, win_errstr(result)));
598 continue;
601 printername = strrchr(info2->printername, '\\');
602 if (printername == NULL) {
603 printername = info2->printername;
604 } else {
605 printername++;
608 if (strequal(printername, aprinter)) {
609 found = true;
610 break;
613 DEBUGADD(10, ("printername: %s\n", printername));
615 TALLOC_FREE(info2);
618 if ( !found ) {
619 if (cache_key != NULL) {
620 gencache_set(cache_key, printer_not_found,
621 time(NULL)+300);
622 TALLOC_FREE(cache_key);
624 DEBUGADD(4,("Printer not found\n"));
625 return false;
628 if (cache_key != NULL) {
629 gencache_set(cache_key, sname, time(NULL)+300);
630 TALLOC_FREE(cache_key);
633 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
635 fstrcpy(Printer->sharename, sname);
637 return true;
640 /****************************************************************************
641 Find first available printer slot. creates a printer handle for you.
642 ****************************************************************************/
644 static bool open_printer_hnd(struct pipes_struct *p, struct policy_handle *hnd,
645 const char *name, uint32_t access_granted)
647 Printer_entry *new_printer;
649 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
651 new_printer = TALLOC_ZERO_P(NULL, Printer_entry);
652 if (new_printer == NULL) {
653 return false;
655 talloc_set_destructor(new_printer, printer_entry_destructor);
657 if (!create_policy_hnd(p, hnd, new_printer)) {
658 TALLOC_FREE(new_printer);
659 return false;
662 /* Add to the internal list. */
663 DLIST_ADD(printers_list, new_printer);
665 new_printer->notify.option=NULL;
667 if (!set_printer_hnd_printertype(new_printer, name)) {
668 close_printer_handle(p, hnd);
669 return false;
672 if (!set_printer_hnd_name(p->mem_ctx, p->server_info, p->msg_ctx,
673 new_printer, name)) {
674 close_printer_handle(p, hnd);
675 return false;
678 new_printer->access_granted = access_granted;
680 DEBUG(5, ("%d printer handles active\n",
681 (int)num_pipe_handles(p)));
683 return true;
686 /***************************************************************************
687 check to see if the client motify handle is monitoring the notification
688 given by (notify_type, notify_field).
689 **************************************************************************/
691 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
692 uint16_t notify_field)
694 return true;
697 static bool is_monitoring_event(Printer_entry *p, uint16_t notify_type,
698 uint16_t notify_field)
700 struct spoolss_NotifyOption *option = p->notify.option;
701 uint32_t i, j;
704 * Flags should always be zero when the change notify
705 * is registered by the client's spooler. A user Win32 app
706 * might use the flags though instead of the NOTIFY_OPTION_INFO
707 * --jerry
710 if (!option) {
711 return false;
714 if (p->notify.flags)
715 return is_monitoring_event_flags(
716 p->notify.flags, notify_type, notify_field);
718 for (i = 0; i < option->count; i++) {
720 /* Check match for notify_type */
722 if (option->types[i].type != notify_type)
723 continue;
725 /* Check match for field */
727 for (j = 0; j < option->types[i].count; j++) {
728 if (option->types[i].fields[j].field == notify_field) {
729 return true;
734 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
735 p->servername, p->sharename, notify_type, notify_field));
737 return false;
740 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
741 _data->data.integer[0] = _integer; \
742 _data->data.integer[1] = 0;
745 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
746 _data->data.string.string = talloc_strdup(mem_ctx, _p); \
747 if (!_data->data.string.string) {\
748 _data->data.string.size = 0; \
750 _data->data.string.size = strlen_m_term(_p) * 2;
752 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
753 _data->data.devmode.devmode = _devmode;
755 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
756 _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
757 if (!_data->data.sd.sd) { \
758 _data->data.sd.sd_size = 0; \
760 _data->data.sd.sd_size = \
761 ndr_size_security_descriptor(_data->data.sd.sd, 0);
763 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
764 struct tm *t,
765 const char **pp,
766 uint32_t *plen)
768 struct spoolss_Time st;
769 uint32_t len = 16;
770 char *p;
772 if (!init_systemtime(&st, t)) {
773 return;
776 p = talloc_array(mem_ctx, char, len);
777 if (!p) {
778 return;
782 * Systemtime must be linearized as a set of UINT16's.
783 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
786 SSVAL(p, 0, st.year);
787 SSVAL(p, 2, st.month);
788 SSVAL(p, 4, st.day_of_week);
789 SSVAL(p, 6, st.day);
790 SSVAL(p, 8, st.hour);
791 SSVAL(p, 10, st.minute);
792 SSVAL(p, 12, st.second);
793 SSVAL(p, 14, st.millisecond);
795 *pp = p;
796 *plen = len;
799 /* Convert a notification message to a struct spoolss_Notify */
801 static void notify_one_value(struct spoolss_notify_msg *msg,
802 struct spoolss_Notify *data,
803 TALLOC_CTX *mem_ctx)
805 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
808 static void notify_string(struct spoolss_notify_msg *msg,
809 struct spoolss_Notify *data,
810 TALLOC_CTX *mem_ctx)
812 /* The length of the message includes the trailing \0 */
814 data->data.string.size = msg->len * 2;
815 data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
816 if (!data->data.string.string) {
817 data->data.string.size = 0;
818 return;
822 static void notify_system_time(struct spoolss_notify_msg *msg,
823 struct spoolss_Notify *data,
824 TALLOC_CTX *mem_ctx)
826 data->data.string.string = NULL;
827 data->data.string.size = 0;
829 if (msg->len != sizeof(time_t)) {
830 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
831 msg->len));
832 return;
835 init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
836 &data->data.string.string,
837 &data->data.string.size);
840 struct notify2_message_table {
841 const char *name;
842 void (*fn)(struct spoolss_notify_msg *msg,
843 struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
846 static struct notify2_message_table printer_notify_table[] = {
847 /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
848 /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
849 /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
850 /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
851 /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
852 /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
853 /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
854 /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
855 /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
856 /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
857 /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
858 /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
859 /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
860 /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
861 /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
862 /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
863 /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
864 /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
865 /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
868 static struct notify2_message_table job_notify_table[] = {
869 /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
870 /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
871 /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
872 /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
873 /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
874 /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
875 /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
876 /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
877 /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
878 /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
879 /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
880 /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
881 /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
882 /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
883 /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
884 /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
885 /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
886 /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
887 /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
888 /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
889 /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
890 /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
891 /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
892 /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
896 /***********************************************************************
897 Allocate talloc context for container object
898 **********************************************************************/
900 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
902 if ( !ctr )
903 return;
905 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
907 return;
910 /***********************************************************************
911 release all allocated memory and zero out structure
912 **********************************************************************/
914 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
916 if ( !ctr )
917 return;
919 if ( ctr->ctx )
920 talloc_destroy(ctr->ctx);
922 ZERO_STRUCTP(ctr);
924 return;
927 /***********************************************************************
928 **********************************************************************/
930 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
932 if ( !ctr )
933 return NULL;
935 return ctr->ctx;
938 /***********************************************************************
939 **********************************************************************/
941 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
943 if ( !ctr || !ctr->msg_groups )
944 return NULL;
946 if ( idx >= ctr->num_groups )
947 return NULL;
949 return &ctr->msg_groups[idx];
953 /***********************************************************************
954 How many groups of change messages do we have ?
955 **********************************************************************/
957 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
959 if ( !ctr )
960 return 0;
962 return ctr->num_groups;
965 /***********************************************************************
966 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
967 **********************************************************************/
969 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
971 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
972 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
973 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
974 int i, new_slot;
976 if ( !ctr || !msg )
977 return 0;
979 /* loop over all groups looking for a matching printer name */
981 for ( i=0; i<ctr->num_groups; i++ ) {
982 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
983 break;
986 /* add a new group? */
988 if ( i == ctr->num_groups ) {
989 ctr->num_groups++;
991 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
992 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
993 return 0;
995 ctr->msg_groups = groups;
997 /* clear the new entry and set the printer name */
999 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1000 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1003 /* add the change messages; 'i' is the correct index now regardless */
1005 msg_grp = &ctr->msg_groups[i];
1007 msg_grp->num_msgs++;
1009 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1010 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1011 return 0;
1013 msg_grp->msgs = msg_list;
1015 new_slot = msg_grp->num_msgs-1;
1016 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1018 /* need to allocate own copy of data */
1020 if ( msg->len != 0 )
1021 msg_grp->msgs[new_slot].notify.data = (char *)
1022 TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
1024 return ctr->num_groups;
1027 static void construct_info_data(struct spoolss_Notify *info_data,
1028 enum spoolss_NotifyType type,
1029 uint16_t field, int id);
1031 /***********************************************************************
1032 Send a change notication message on all handles which have a call
1033 back registered
1034 **********************************************************************/
1036 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1038 Printer_entry *p;
1039 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
1040 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1041 SPOOLSS_NOTIFY_MSG *messages;
1042 int sending_msg_count;
1044 if ( !msg_group ) {
1045 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1046 return;
1049 messages = msg_group->msgs;
1051 if ( !messages ) {
1052 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
1053 return;
1056 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1058 /* loop over all printers */
1060 for (p = printers_list; p; p = p->next) {
1061 struct spoolss_Notify *notifies;
1062 uint32_t count = 0;
1063 uint32_t id;
1064 int i;
1066 /* Is there notification on this handle? */
1068 if ( !p->notify.client_connected )
1069 continue;
1071 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
1073 /* For this printer? Print servers always receive
1074 notifications. */
1076 if ( ( p->printer_type == SPLHND_PRINTER ) &&
1077 ( !strequal(msg_group->printername, p->sharename) ) )
1078 continue;
1080 DEBUG(10,("Our printer\n"));
1082 /* allocate the max entries possible */
1084 notifies = TALLOC_ZERO_ARRAY(mem_ctx, struct spoolss_Notify, msg_group->num_msgs);
1085 if (!notifies) {
1086 return;
1089 /* build the array of change notifications */
1091 sending_msg_count = 0;
1093 for ( i=0; i<msg_group->num_msgs; i++ ) {
1094 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
1096 /* Are we monitoring this event? */
1098 if (!is_monitoring_event(p, msg->type, msg->field))
1099 continue;
1101 sending_msg_count++;
1104 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1105 msg->type, msg->field, p->sharename));
1108 * if the is a printer notification handle and not a job notification
1109 * type, then set the id to 0. Other wise just use what was specified
1110 * in the message.
1112 * When registering change notification on a print server handle
1113 * we always need to send back the id (snum) matching the printer
1114 * for which the change took place. For change notify registered
1115 * on a printer handle, this does not matter and the id should be 0.
1117 * --jerry
1120 if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1121 id = 0;
1122 else
1123 id = msg->id;
1126 /* Convert unix jobid to smb jobid */
1128 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1129 id = sysjob_to_jobid(msg->id);
1131 if (id == -1) {
1132 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1133 goto done;
1137 construct_info_data(&notifies[count],
1138 (enum spoolss_NotifyType) msg->type,
1139 msg->field,
1140 id);
1142 switch(msg->type) {
1143 case PRINTER_NOTIFY_TYPE:
1144 if ( printer_notify_table[msg->field].fn )
1145 printer_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1146 break;
1148 case JOB_NOTIFY_TYPE:
1149 if ( job_notify_table[msg->field].fn )
1150 job_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
1151 break;
1153 default:
1154 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1155 goto done;
1158 count++;
1161 if ( sending_msg_count ) {
1162 NTSTATUS status;
1163 WERROR werr;
1164 union spoolss_ReplyPrinterInfo info;
1165 struct spoolss_NotifyInfo info0;
1166 uint32_t reply_result;
1168 info0.version = 0x2;
1169 info0.flags = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1170 info0.count = count;
1171 info0.notifies = notifies;
1173 info.info0 = &info0;
1175 status = rpccli_spoolss_RouterReplyPrinterEx(notify_cli_pipe, mem_ctx,
1176 &p->notify.client_hnd,
1177 p->notify.change, /* color */
1178 p->notify.flags,
1179 &reply_result,
1180 0, /* reply_type, must be 0 */
1181 info,
1182 &werr);
1183 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr)) {
1184 DEBUG(1,("RouterReplyPrinterEx to client: %s failed: %s\n",
1185 notify_cli_pipe->srv_name_slash,
1186 win_errstr(werr)));
1188 switch (reply_result) {
1189 case 0:
1190 break;
1191 case PRINTER_NOTIFY_INFO_DISCARDED:
1192 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1193 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1194 break;
1195 default:
1196 break;
1201 done:
1202 DEBUG(8,("send_notify2_changes: Exit...\n"));
1203 return;
1206 /***********************************************************************
1207 **********************************************************************/
1209 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1212 uint32_t tv_sec, tv_usec;
1213 size_t offset = 0;
1215 /* Unpack message */
1217 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1218 msg->printer);
1220 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1221 &tv_sec, &tv_usec,
1222 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1224 if (msg->len == 0)
1225 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1226 &msg->notify.value[0], &msg->notify.value[1]);
1227 else
1228 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1229 &msg->len, &msg->notify.data);
1231 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1232 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1234 tv->tv_sec = tv_sec;
1235 tv->tv_usec = tv_usec;
1237 if (msg->len == 0)
1238 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1239 msg->notify.value[1]));
1240 else
1241 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1243 return true;
1246 /********************************************************************
1247 Receive a notify2 message list
1248 ********************************************************************/
1250 static void receive_notify2_message_list(struct messaging_context *msg,
1251 void *private_data,
1252 uint32_t msg_type,
1253 struct server_id server_id,
1254 DATA_BLOB *data)
1256 size_t msg_count, i;
1257 char *buf = (char *)data->data;
1258 char *msg_ptr;
1259 size_t msg_len;
1260 SPOOLSS_NOTIFY_MSG notify;
1261 SPOOLSS_NOTIFY_MSG_CTR messages;
1262 int num_groups;
1264 if (data->length < 4) {
1265 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1266 return;
1269 msg_count = IVAL(buf, 0);
1270 msg_ptr = buf + 4;
1272 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1274 if (msg_count == 0) {
1275 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1276 return;
1279 /* initialize the container */
1281 ZERO_STRUCT( messages );
1282 notify_msg_ctr_init( &messages );
1285 * build message groups for each printer identified
1286 * in a change_notify msg. Remember that a PCN message
1287 * includes the handle returned for the srv_spoolss_replyopenprinter()
1288 * call. Therefore messages are grouped according to printer handle.
1291 for ( i=0; i<msg_count; i++ ) {
1292 struct timeval msg_tv;
1294 if (msg_ptr + 4 - buf > data->length) {
1295 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1296 return;
1299 msg_len = IVAL(msg_ptr,0);
1300 msg_ptr += 4;
1302 if (msg_ptr + msg_len - buf > data->length) {
1303 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1304 return;
1307 /* unpack messages */
1309 ZERO_STRUCT( notify );
1310 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1311 msg_ptr += msg_len;
1313 /* add to correct list in container */
1315 notify_msg_ctr_addmsg( &messages, &notify );
1317 /* free memory that might have been allocated by notify2_unpack_msg() */
1319 if ( notify.len != 0 )
1320 SAFE_FREE( notify.notify.data );
1323 /* process each group of messages */
1325 num_groups = notify_msg_ctr_numgroups( &messages );
1326 for ( i=0; i<num_groups; i++ )
1327 send_notify2_changes( &messages, i );
1330 /* cleanup */
1332 DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1333 (uint32_t)msg_count ));
1335 notify_msg_ctr_destroy( &messages );
1337 return;
1340 /********************************************************************
1341 Send a message to ourself about new driver being installed
1342 so we can upgrade the information for each printer bound to this
1343 driver
1344 ********************************************************************/
1346 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1347 struct messaging_context *msg_ctx)
1349 int len = strlen(drivername);
1351 if (!len)
1352 return false;
1354 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1355 drivername));
1357 messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1358 MSG_PRINTER_DRVUPGRADE,
1359 (uint8_t *)drivername, len+1);
1361 return true;
1364 /**********************************************************************
1365 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1366 over all printers, upgrading ones as necessary
1367 **********************************************************************/
1369 void do_drv_upgrade_printer(struct messaging_context *msg,
1370 void *private_data,
1371 uint32_t msg_type,
1372 struct server_id server_id,
1373 DATA_BLOB *data)
1375 TALLOC_CTX *tmp_ctx;
1376 struct auth_serversupplied_info *server_info = NULL;
1377 struct spoolss_PrinterInfo2 *pinfo2;
1378 NTSTATUS status;
1379 WERROR result;
1380 const char *drivername;
1381 int snum;
1382 int n_services = lp_numservices();
1383 size_t len;
1385 tmp_ctx = talloc_new(NULL);
1386 if (!tmp_ctx) return;
1388 status = make_server_info_system(tmp_ctx, &server_info);
1389 if (!NT_STATUS_IS_OK(status)) {
1390 DEBUG(0, ("do_drv_upgrade_printer: "
1391 "Could not create system server_info\n"));
1392 goto done;
1395 len = MIN(data->length,sizeof(drivername)-1);
1396 drivername = talloc_strndup(tmp_ctx, (const char *)data->data, len);
1397 if (!drivername) {
1398 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1399 goto done;
1402 DEBUG(10, ("do_drv_upgrade_printer: "
1403 "Got message for new driver [%s]\n", drivername));
1405 /* Iterate the printer list */
1407 for (snum = 0; snum < n_services; snum++) {
1408 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1409 continue;
1412 result = winreg_get_printer(tmp_ctx, server_info, msg,
1413 NULL,
1414 lp_const_servicename(snum),
1415 &pinfo2);
1417 if (!W_ERROR_IS_OK(result)) {
1418 continue;
1421 if (!pinfo2->drivername) {
1422 continue;
1425 if (strcmp(drivername, pinfo2->drivername) != 0) {
1426 continue;
1429 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1431 /* all we care about currently is the change_id */
1432 result = winreg_printer_update_changeid(tmp_ctx,
1433 server_info,
1434 msg,
1435 pinfo2->printername);
1437 if (!W_ERROR_IS_OK(result)) {
1438 DEBUG(3, ("do_drv_upgrade_printer: "
1439 "Failed to update changeid [%s]\n",
1440 win_errstr(result)));
1444 /* all done */
1445 done:
1446 talloc_free(tmp_ctx);
1449 /********************************************************************
1450 Update the cache for all printq's with a registered client
1451 connection
1452 ********************************************************************/
1454 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1456 Printer_entry *printer = printers_list;
1457 int snum;
1459 /* loop through all printers and update the cache where
1460 client_connected == true */
1461 while ( printer )
1463 if ( (printer->printer_type == SPLHND_PRINTER)
1464 && printer->notify.client_connected )
1466 snum = print_queue_snum(printer->sharename);
1467 print_queue_status(msg_ctx, snum, NULL, NULL );
1470 printer = printer->next;
1473 return;
1476 /****************************************************************
1477 _spoolss_OpenPrinter
1478 ****************************************************************/
1480 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1481 struct spoolss_OpenPrinter *r)
1483 struct spoolss_OpenPrinterEx e;
1484 WERROR werr;
1486 ZERO_STRUCT(e.in.userlevel);
1488 e.in.printername = r->in.printername;
1489 e.in.datatype = r->in.datatype;
1490 e.in.devmode_ctr = r->in.devmode_ctr;
1491 e.in.access_mask = r->in.access_mask;
1492 e.in.level = 0;
1494 e.out.handle = r->out.handle;
1496 werr = _spoolss_OpenPrinterEx(p, &e);
1498 if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1499 /* OpenPrinterEx returns this for a bad
1500 * printer name. We must return WERR_INVALID_PRINTER_NAME
1501 * instead.
1503 werr = WERR_INVALID_PRINTER_NAME;
1506 return werr;
1509 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1510 struct spoolss_DeviceMode *orig,
1511 struct spoolss_DeviceMode **dest)
1513 struct spoolss_DeviceMode *dm;
1515 dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1516 if (!dm) {
1517 return WERR_NOMEM;
1520 /* copy all values, then duplicate strings and structs */
1521 *dm = *orig;
1523 dm->devicename = talloc_strdup(dm, orig->devicename);
1524 if (!dm->devicename) {
1525 return WERR_NOMEM;
1527 dm->formname = talloc_strdup(dm, orig->formname);
1528 if (!dm->formname) {
1529 return WERR_NOMEM;
1531 if (orig->driverextra_data.data) {
1532 dm->driverextra_data.data =
1533 (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1534 orig->driverextra_data.length);
1535 if (!dm->driverextra_data.data) {
1536 return WERR_NOMEM;
1540 *dest = dm;
1541 return WERR_OK;
1544 /****************************************************************
1545 _spoolss_OpenPrinterEx
1546 ****************************************************************/
1548 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1549 struct spoolss_OpenPrinterEx *r)
1551 int snum;
1552 Printer_entry *Printer=NULL;
1554 if (!r->in.printername) {
1555 return WERR_INVALID_PARAM;
1558 /* some sanity check because you can open a printer or a print server */
1559 /* aka: \\server\printer or \\server */
1561 DEBUGADD(3,("checking name: %s\n", r->in.printername));
1563 if (!open_printer_hnd(p, r->out.handle, r->in.printername, 0)) {
1564 DEBUG(0,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1565 "for printer %s\n", r->in.printername));
1566 ZERO_STRUCTP(r->out.handle);
1567 return WERR_INVALID_PARAM;
1570 Printer = find_printer_index_by_hnd(p, r->out.handle);
1571 if ( !Printer ) {
1572 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1573 "handle we created for printer %s\n", r->in.printername));
1574 close_printer_handle(p, r->out.handle);
1575 ZERO_STRUCTP(r->out.handle);
1576 return WERR_INVALID_PARAM;
1580 * First case: the user is opening the print server:
1582 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1583 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1585 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1586 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1587 * or if the user is listed in the smb.conf printer admin parameter.
1589 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1590 * client view printer folder, but does not show the MSAPW.
1592 * Note: this test needs code to check access rights here too. Jeremy
1593 * could you look at this?
1595 * Second case: the user is opening a printer:
1596 * NT doesn't let us connect to a printer if the connecting user
1597 * doesn't have print permission.
1599 * Third case: user is opening a Port Monitor
1600 * access checks same as opening a handle to the print server.
1603 switch (Printer->printer_type )
1605 case SPLHND_SERVER:
1606 case SPLHND_PORTMON_TCP:
1607 case SPLHND_PORTMON_LOCAL:
1608 /* Printserver handles use global struct... */
1610 snum = -1;
1612 /* Map standard access rights to object specific access rights */
1614 se_map_standard(&r->in.access_mask,
1615 &printserver_std_mapping);
1617 /* Deny any object specific bits that don't apply to print
1618 servers (i.e printer and job specific bits) */
1620 r->in.access_mask &= SEC_MASK_SPECIFIC;
1622 if (r->in.access_mask &
1623 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1624 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1625 close_printer_handle(p, r->out.handle);
1626 ZERO_STRUCTP(r->out.handle);
1627 return WERR_ACCESS_DENIED;
1630 /* Allow admin access */
1632 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1634 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1636 if (!lp_ms_add_printer_wizard()) {
1637 close_printer_handle(p, r->out.handle);
1638 ZERO_STRUCTP(r->out.handle);
1639 return WERR_ACCESS_DENIED;
1642 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1643 and not a printer admin, then fail */
1645 if ((p->server_info->utok.uid != sec_initial_uid()) &&
1646 !user_has_privileges(p->server_info->ptok,
1647 &se_printop ) &&
1648 !token_contains_name_in_list(
1649 uidtoname(p->server_info->utok.uid),
1650 p->server_info->info3->base.domain.string,
1651 NULL,
1652 p->server_info->ptok,
1653 lp_printer_admin(snum))) {
1654 close_printer_handle(p, r->out.handle);
1655 ZERO_STRUCTP(r->out.handle);
1656 return WERR_ACCESS_DENIED;
1659 r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1661 else
1663 r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1666 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1667 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1669 /* We fall through to return WERR_OK */
1670 break;
1672 case SPLHND_PRINTER:
1673 /* NT doesn't let us connect to a printer if the connecting user
1674 doesn't have print permission. */
1676 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1677 close_printer_handle(p, r->out.handle);
1678 ZERO_STRUCTP(r->out.handle);
1679 return WERR_BADFID;
1682 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1683 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1686 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1688 /* map an empty access mask to the minimum access mask */
1689 if (r->in.access_mask == 0x0)
1690 r->in.access_mask = PRINTER_ACCESS_USE;
1693 * If we are not serving the printer driver for this printer,
1694 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1695 * will keep NT clients happy --jerry
1698 if (lp_use_client_driver(snum)
1699 && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1701 r->in.access_mask = PRINTER_ACCESS_USE;
1704 /* check smb.conf parameters and the the sec_desc */
1706 if (!allow_access(lp_hostsdeny(snum), lp_hostsallow(snum),
1707 p->client_id->name, p->client_id->addr)) {
1708 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1709 ZERO_STRUCTP(r->out.handle);
1710 return WERR_ACCESS_DENIED;
1713 if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
1714 p->server_info->ptok, snum) ||
1715 !print_access_check(p->server_info, p->msg_ctx, snum,
1716 r->in.access_mask)) {
1717 DEBUG(3, ("access DENIED for printer open\n"));
1718 close_printer_handle(p, r->out.handle);
1719 ZERO_STRUCTP(r->out.handle);
1720 return WERR_ACCESS_DENIED;
1723 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1724 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1725 close_printer_handle(p, r->out.handle);
1726 ZERO_STRUCTP(r->out.handle);
1727 return WERR_ACCESS_DENIED;
1730 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1731 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1732 else
1733 r->in.access_mask = PRINTER_ACCESS_USE;
1735 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1736 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1738 winreg_create_printer(p->mem_ctx,
1739 p->server_info,
1740 p->msg_ctx,
1741 Printer->servername,
1742 lp_const_servicename(snum));
1744 break;
1746 default:
1747 /* sanity check to prevent programmer error */
1748 ZERO_STRUCTP(r->out.handle);
1749 return WERR_BADFID;
1752 Printer->access_granted = r->in.access_mask;
1755 * If the client sent a devmode in the OpenPrinter() call, then
1756 * save it here in case we get a job submission on this handle
1759 if ((Printer->printer_type != SPLHND_SERVER) &&
1760 r->in.devmode_ctr.devmode) {
1761 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1762 &Printer->devmode);
1765 #if 0 /* JERRY -- I'm doubtful this is really effective */
1766 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1767 optimization in Windows 2000 clients --jerry */
1769 if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1770 && (RA_WIN2K == get_remote_arch()) )
1772 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1773 sys_usleep( 500000 );
1775 #endif
1777 return WERR_OK;
1780 /****************************************************************
1781 _spoolss_ClosePrinter
1782 ****************************************************************/
1784 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1785 struct spoolss_ClosePrinter *r)
1787 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
1789 if (Printer && Printer->document_started) {
1790 struct spoolss_EndDocPrinter e;
1792 e.in.handle = r->in.handle;
1794 _spoolss_EndDocPrinter(p, &e);
1797 if (!close_printer_handle(p, r->in.handle))
1798 return WERR_BADFID;
1800 /* clear the returned printer handle. Observed behavior
1801 from Win2k server. Don't think this really matters.
1802 Previous code just copied the value of the closed
1803 handle. --jerry */
1805 ZERO_STRUCTP(r->out.handle);
1807 return WERR_OK;
1810 /****************************************************************
1811 _spoolss_DeletePrinter
1812 ****************************************************************/
1814 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
1815 struct spoolss_DeletePrinter *r)
1817 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
1818 WERROR result;
1819 int snum;
1821 if (Printer && Printer->document_started) {
1822 struct spoolss_EndDocPrinter e;
1824 e.in.handle = r->in.handle;
1826 _spoolss_EndDocPrinter(p, &e);
1829 if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
1830 winreg_delete_printer_key(p->mem_ctx,
1831 p->server_info,
1832 p->msg_ctx,
1833 lp_const_servicename(snum),
1834 "");
1837 result = delete_printer_handle(p, r->in.handle);
1839 return result;
1842 /*******************************************************************
1843 * static function to lookup the version id corresponding to an
1844 * long architecture string
1845 ******************************************************************/
1847 static const struct print_architecture_table_node archi_table[]= {
1849 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
1850 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
1851 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
1852 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
1853 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
1854 {"Windows IA64", SPL_ARCH_IA64, 3 },
1855 {"Windows x64", SPL_ARCH_X64, 3 },
1856 {NULL, "", -1 }
1859 static int get_version_id(const char *arch)
1861 int i;
1863 for (i=0; archi_table[i].long_archi != NULL; i++)
1865 if (strcmp(arch, archi_table[i].long_archi) == 0)
1866 return (archi_table[i].version);
1869 return -1;
1872 /****************************************************************
1873 _spoolss_DeletePrinterDriver
1874 ****************************************************************/
1876 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
1877 struct spoolss_DeletePrinterDriver *r)
1880 struct spoolss_DriverInfo8 *info = NULL;
1881 struct spoolss_DriverInfo8 *info_win2k = NULL;
1882 int version;
1883 WERROR status;
1884 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1886 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1887 and not a printer admin, then fail */
1889 if ( (p->server_info->utok.uid != sec_initial_uid())
1890 && !user_has_privileges(p->server_info->ptok, &se_printop )
1891 && !token_contains_name_in_list(
1892 uidtoname(p->server_info->utok.uid),
1893 p->server_info->info3->base.domain.string,
1894 NULL,
1895 p->server_info->ptok,
1896 lp_printer_admin(-1)) )
1898 return WERR_ACCESS_DENIED;
1901 /* check that we have a valid driver name first */
1903 if ((version = get_version_id(r->in.architecture)) == -1)
1904 return WERR_INVALID_ENVIRONMENT;
1906 status = winreg_get_driver(p->mem_ctx, p->server_info, p->msg_ctx,
1907 r->in.architecture, r->in.driver,
1908 version, &info);
1909 if (!W_ERROR_IS_OK(status)) {
1910 /* try for Win2k driver if "Windows NT x86" */
1912 if ( version == 2 ) {
1913 version = 3;
1915 status = winreg_get_driver(p->mem_ctx, p->server_info,
1916 p->msg_ctx,
1917 r->in.architecture,
1918 r->in.driver,
1919 version, &info);
1920 if (!W_ERROR_IS_OK(status)) {
1921 status = WERR_UNKNOWN_PRINTER_DRIVER;
1922 goto done;
1925 /* otherwise it was a failure */
1926 else {
1927 status = WERR_UNKNOWN_PRINTER_DRIVER;
1928 goto done;
1933 if (printer_driver_in_use(p->mem_ctx, p->server_info, p->msg_ctx,
1934 info)) {
1935 status = WERR_PRINTER_DRIVER_IN_USE;
1936 goto done;
1939 if (version == 2) {
1940 status = winreg_get_driver(p->mem_ctx, p->server_info,
1941 p->msg_ctx,
1942 r->in.architecture,
1943 r->in.driver, 3, &info_win2k);
1944 if (W_ERROR_IS_OK(status)) {
1945 /* if we get to here, we now have 2 driver info structures to remove */
1946 /* remove the Win2k driver first*/
1948 status = winreg_del_driver(p->mem_ctx,
1949 p->server_info,
1950 p->msg_ctx,
1951 info_win2k, 3);
1952 talloc_free(info_win2k);
1954 /* this should not have failed---if it did, report to client */
1955 if (!W_ERROR_IS_OK(status)) {
1956 goto done;
1961 status = winreg_del_driver(p->mem_ctx, p->server_info, p->msg_ctx,
1962 info, version);
1964 done:
1965 talloc_free(info);
1967 return status;
1970 /****************************************************************
1971 _spoolss_DeletePrinterDriverEx
1972 ****************************************************************/
1974 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
1975 struct spoolss_DeletePrinterDriverEx *r)
1977 struct spoolss_DriverInfo8 *info = NULL;
1978 struct spoolss_DriverInfo8 *info_win2k = NULL;
1979 int version;
1980 bool delete_files;
1981 WERROR status;
1982 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1984 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1985 and not a printer admin, then fail */
1987 if ( (p->server_info->utok.uid != sec_initial_uid())
1988 && !user_has_privileges(p->server_info->ptok, &se_printop )
1989 && !token_contains_name_in_list(
1990 uidtoname(p->server_info->utok.uid),
1991 p->server_info->info3->base.domain.string,
1992 NULL,
1993 p->server_info->ptok, lp_printer_admin(-1)) )
1995 return WERR_ACCESS_DENIED;
1998 /* check that we have a valid driver name first */
1999 if ((version = get_version_id(r->in.architecture)) == -1) {
2000 /* this is what NT returns */
2001 return WERR_INVALID_ENVIRONMENT;
2004 if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2005 version = r->in.version;
2007 status = winreg_get_driver(p->mem_ctx, p->server_info,
2008 p->msg_ctx, r->in.architecture,
2009 r->in.driver, version, &info);
2010 if (!W_ERROR_IS_OK(status)) {
2011 status = WERR_UNKNOWN_PRINTER_DRIVER;
2014 * if the client asked for a specific version,
2015 * or this is something other than Windows NT x86,
2016 * then we've failed
2019 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2020 goto done;
2022 /* try for Win2k driver if "Windows NT x86" */
2024 version = 3;
2025 status = winreg_get_driver(info, p->server_info, p->msg_ctx,
2026 r->in.architecture,
2027 r->in.driver,
2028 version, &info);
2029 if (!W_ERROR_IS_OK(status)) {
2030 status = WERR_UNKNOWN_PRINTER_DRIVER;
2031 goto done;
2035 if (printer_driver_in_use(info, p->server_info, p->msg_ctx, info)) {
2036 status = WERR_PRINTER_DRIVER_IN_USE;
2037 goto done;
2041 * we have a couple of cases to consider.
2042 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2043 * then the delete should fail if **any** files overlap with
2044 * other drivers
2045 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2046 * non-overlapping files
2047 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2048 * is set, the do not delete any files
2049 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2052 delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2054 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2056 if (delete_files &&
2057 (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2058 printer_driver_files_in_use(info, p->server_info, p->msg_ctx,
2059 info)) {
2060 /* no idea of the correct error here */
2061 status = WERR_ACCESS_DENIED;
2062 goto done;
2066 /* also check for W32X86/3 if necessary; maybe we already have? */
2068 if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2069 status = winreg_get_driver(info, p->server_info, p->msg_ctx,
2070 r->in.architecture,
2071 r->in.driver, 3, &info_win2k);
2072 if (W_ERROR_IS_OK(status)) {
2074 if (delete_files &&
2075 (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2076 printer_driver_files_in_use(info, p->server_info,
2077 p->msg_ctx,
2078 info_win2k)) {
2079 /* no idea of the correct error here */
2080 talloc_free(info_win2k);
2081 status = WERR_ACCESS_DENIED;
2082 goto done;
2085 /* if we get to here, we now have 2 driver info structures to remove */
2086 /* remove the Win2k driver first*/
2088 status = winreg_del_driver(info, p->server_info,
2089 p->msg_ctx, info_win2k, 3);
2091 /* this should not have failed---if it did, report to client */
2093 if (!W_ERROR_IS_OK(status)) {
2094 goto done;
2098 * now delete any associated files if delete_files is
2099 * true. Even if this part failes, we return succes
2100 * because the driver doesn not exist any more
2102 if (delete_files) {
2103 delete_driver_files(p->server_info,
2104 info_win2k);
2109 status = winreg_del_driver(info, p->server_info, p->msg_ctx, info,
2110 version);
2111 if (!W_ERROR_IS_OK(status)) {
2112 goto done;
2116 * now delete any associated files if delete_files is
2117 * true. Even if this part failes, we return succes
2118 * because the driver doesn not exist any more
2120 if (delete_files) {
2121 delete_driver_files(p->server_info, info);
2124 done:
2125 talloc_free(info);
2126 return status;
2130 /********************************************************************
2131 GetPrinterData on a printer server Handle.
2132 ********************************************************************/
2134 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2135 const char *value,
2136 enum winreg_Type *type,
2137 union spoolss_PrinterData *data)
2139 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2141 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2142 *type = REG_DWORD;
2143 data->value = 0x00;
2144 return WERR_OK;
2147 if (!StrCaseCmp(value, "BeepEnabled")) {
2148 *type = REG_DWORD;
2149 data->value = 0x00;
2150 return WERR_OK;
2153 if (!StrCaseCmp(value, "EventLog")) {
2154 *type = REG_DWORD;
2155 /* formally was 0x1b */
2156 data->value = 0x00;
2157 return WERR_OK;
2160 if (!StrCaseCmp(value, "NetPopup")) {
2161 *type = REG_DWORD;
2162 data->value = 0x00;
2163 return WERR_OK;
2166 if (!StrCaseCmp(value, "MajorVersion")) {
2167 *type = REG_DWORD;
2169 /* Windows NT 4.0 seems to not allow uploading of drivers
2170 to a server that reports 0x3 as the MajorVersion.
2171 need to investigate more how Win2k gets around this .
2172 -- jerry */
2174 if (RA_WINNT == get_remote_arch()) {
2175 data->value = 0x02;
2176 } else {
2177 data->value = 0x03;
2180 return WERR_OK;
2183 if (!StrCaseCmp(value, "MinorVersion")) {
2184 *type = REG_DWORD;
2185 data->value = 0x00;
2186 return WERR_OK;
2189 /* REG_BINARY
2190 * uint32_t size = 0x114
2191 * uint32_t major = 5
2192 * uint32_t minor = [0|1]
2193 * uint32_t build = [2195|2600]
2194 * extra unicode string = e.g. "Service Pack 3"
2196 if (!StrCaseCmp(value, "OSVersion")) {
2197 DATA_BLOB blob;
2198 enum ndr_err_code ndr_err;
2199 struct spoolss_OSVersion os;
2201 os.major = 5; /* Windows 2000 == 5.0 */
2202 os.minor = 0;
2203 os.build = 2195; /* build */
2204 os.extra_string = ""; /* leave extra string empty */
2206 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2207 (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2208 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2209 return WERR_GENERAL_FAILURE;
2212 *type = REG_BINARY;
2213 data->binary = blob;
2215 return WERR_OK;
2219 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2220 *type = REG_SZ;
2222 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2223 W_ERROR_HAVE_NO_MEMORY(data->string);
2225 return WERR_OK;
2228 if (!StrCaseCmp(value, "Architecture")) {
2229 *type = REG_SZ;
2230 data->string = talloc_strdup(mem_ctx,
2231 lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2232 W_ERROR_HAVE_NO_MEMORY(data->string);
2234 return WERR_OK;
2237 if (!StrCaseCmp(value, "DsPresent")) {
2238 *type = REG_DWORD;
2240 /* only show the publish check box if we are a
2241 member of a AD domain */
2243 if (lp_security() == SEC_ADS) {
2244 data->value = 0x01;
2245 } else {
2246 data->value = 0x00;
2248 return WERR_OK;
2251 if (!StrCaseCmp(value, "DNSMachineName")) {
2252 const char *hostname = get_mydnsfullname();
2254 if (!hostname) {
2255 return WERR_BADFILE;
2258 *type = REG_SZ;
2259 data->string = talloc_strdup(mem_ctx, hostname);
2260 W_ERROR_HAVE_NO_MEMORY(data->string);
2262 return WERR_OK;
2265 *type = REG_NONE;
2267 return WERR_INVALID_PARAM;
2270 /****************************************************************
2271 _spoolss_GetPrinterData
2272 ****************************************************************/
2274 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2275 struct spoolss_GetPrinterData *r)
2277 struct spoolss_GetPrinterDataEx r2;
2279 r2.in.handle = r->in.handle;
2280 r2.in.key_name = "PrinterDriverData";
2281 r2.in.value_name = r->in.value_name;
2282 r2.in.offered = r->in.offered;
2283 r2.out.type = r->out.type;
2284 r2.out.data = r->out.data;
2285 r2.out.needed = r->out.needed;
2287 return _spoolss_GetPrinterDataEx(p, &r2);
2290 /*********************************************************
2291 Connect to the client machine.
2292 **********************************************************/
2294 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2295 struct sockaddr_storage *client_ss, const char *remote_machine)
2297 NTSTATUS ret;
2298 struct cli_state *the_cli;
2299 struct sockaddr_storage rm_addr;
2300 char addr[INET6_ADDRSTRLEN];
2302 if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2303 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2304 remote_machine));
2305 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2306 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2307 return false;
2309 print_sockaddr(addr, sizeof(addr), &rm_addr);
2310 } else {
2311 rm_addr = *client_ss;
2312 print_sockaddr(addr, sizeof(addr), &rm_addr);
2313 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2314 addr));
2317 if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2318 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2319 addr));
2320 return false;
2323 /* setup the connection */
2324 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2325 &rm_addr, 0, "IPC$", "IPC",
2326 "", /* username */
2327 "", /* domain */
2328 "", /* password */
2329 0, lp_client_signing(), NULL );
2331 if ( !NT_STATUS_IS_OK( ret ) ) {
2332 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2333 remote_machine ));
2334 return false;
2337 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2338 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2339 cli_shutdown(the_cli);
2340 return false;
2344 * Ok - we have an anonymous connection to the IPC$ share.
2345 * Now start the NT Domain stuff :-).
2348 ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2349 if (!NT_STATUS_IS_OK(ret)) {
2350 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2351 remote_machine, nt_errstr(ret)));
2352 cli_shutdown(the_cli);
2353 return false;
2356 return true;
2359 /***************************************************************************
2360 Connect to the client.
2361 ****************************************************************************/
2363 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2364 uint32_t localprinter,
2365 enum winreg_Type type,
2366 struct policy_handle *handle,
2367 struct sockaddr_storage *client_ss,
2368 struct messaging_context *msg_ctx)
2370 WERROR result;
2371 NTSTATUS status;
2374 * If it's the first connection, contact the client
2375 * and connect to the IPC$ share anonymously
2377 if (smb_connections==0) {
2378 fstring unix_printer;
2380 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2382 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ss, unix_printer ))
2383 return false;
2385 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2386 receive_notify2_message_list);
2387 /* Tell the connections db we're now interested in printer
2388 * notify messages. */
2389 serverid_register_msg_flags(messaging_server_id(msg_ctx),
2390 true, FLAG_MSG_PRINT_NOTIFY);
2394 * Tell the specific printing tdb we want messages for this printer
2395 * by registering our PID.
2398 if (!print_notify_register_pid(snum))
2399 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2401 smb_connections++;
2403 status = rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe, talloc_tos(),
2404 printer,
2405 localprinter,
2406 type,
2408 NULL,
2409 handle,
2410 &result);
2411 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
2412 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2413 win_errstr(result)));
2415 return (W_ERROR_IS_OK(result));
2418 /****************************************************************
2419 ****************************************************************/
2421 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2422 const struct spoolss_NotifyOption *r)
2424 struct spoolss_NotifyOption *option;
2425 uint32_t i,k;
2427 if (!r) {
2428 return NULL;
2431 option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2432 if (!option) {
2433 return NULL;
2436 *option = *r;
2438 if (!option->count) {
2439 return option;
2442 option->types = talloc_zero_array(option,
2443 struct spoolss_NotifyOptionType, option->count);
2444 if (!option->types) {
2445 talloc_free(option);
2446 return NULL;
2449 for (i=0; i < option->count; i++) {
2450 option->types[i] = r->types[i];
2452 if (option->types[i].count) {
2453 option->types[i].fields = talloc_zero_array(option,
2454 union spoolss_Field, option->types[i].count);
2455 if (!option->types[i].fields) {
2456 talloc_free(option);
2457 return NULL;
2459 for (k=0; k<option->types[i].count; k++) {
2460 option->types[i].fields[k] =
2461 r->types[i].fields[k];
2466 return option;
2469 /****************************************************************
2470 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2472 * before replying OK: status=0 a rpc call is made to the workstation
2473 * asking ReplyOpenPrinter
2475 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2476 * called from api_spoolss_rffpcnex
2477 ****************************************************************/
2479 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2480 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2482 int snum = -1;
2483 struct spoolss_NotifyOption *option = r->in.notify_options;
2484 struct sockaddr_storage client_ss;
2486 /* store the notify value in the printer struct */
2488 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2490 if (!Printer) {
2491 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2492 "Invalid handle (%s:%u:%u).\n",
2493 OUR_HANDLE(r->in.handle)));
2494 return WERR_BADFID;
2497 Printer->notify.flags = r->in.flags;
2498 Printer->notify.options = r->in.options;
2499 Printer->notify.printerlocal = r->in.printer_local;
2500 Printer->notify.msg_ctx = p->msg_ctx;
2502 TALLOC_FREE(Printer->notify.option);
2503 Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2505 fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2507 /* Connect to the client machine and send a ReplyOpenPrinter */
2509 if ( Printer->printer_type == SPLHND_SERVER)
2510 snum = -1;
2511 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2512 !get_printer_snum(p, r->in.handle, &snum, NULL) )
2513 return WERR_BADFID;
2515 DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2516 "client_address is %s\n", p->client_id->addr));
2518 if (!interpret_string_addr(&client_ss, p->client_id->addr,
2519 AI_NUMERICHOST)) {
2520 return WERR_SERVER_UNAVAILABLE;
2523 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2524 Printer->notify.printerlocal, REG_SZ,
2525 &Printer->notify.client_hnd,
2526 &client_ss, p->msg_ctx))
2527 return WERR_SERVER_UNAVAILABLE;
2529 Printer->notify.client_connected = true;
2531 return WERR_OK;
2534 /*******************************************************************
2535 * fill a notify_info_data with the servername
2536 ********************************************************************/
2538 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2539 int snum,
2540 struct spoolss_Notify *data,
2541 print_queue_struct *queue,
2542 struct spoolss_PrinterInfo2 *pinfo2,
2543 TALLOC_CTX *mem_ctx)
2545 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2548 /*******************************************************************
2549 * fill a notify_info_data with the printername (not including the servername).
2550 ********************************************************************/
2552 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2553 int snum,
2554 struct spoolss_Notify *data,
2555 print_queue_struct *queue,
2556 struct spoolss_PrinterInfo2 *pinfo2,
2557 TALLOC_CTX *mem_ctx)
2559 /* the notify name should not contain the \\server\ part */
2560 const char *p = strrchr(pinfo2->printername, '\\');
2562 if (!p) {
2563 p = pinfo2->printername;
2564 } else {
2565 p++;
2568 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2571 /*******************************************************************
2572 * fill a notify_info_data with the servicename
2573 ********************************************************************/
2575 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2576 int snum,
2577 struct spoolss_Notify *data,
2578 print_queue_struct *queue,
2579 struct spoolss_PrinterInfo2 *pinfo2,
2580 TALLOC_CTX *mem_ctx)
2582 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2585 /*******************************************************************
2586 * fill a notify_info_data with the port name
2587 ********************************************************************/
2589 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2590 int snum,
2591 struct spoolss_Notify *data,
2592 print_queue_struct *queue,
2593 struct spoolss_PrinterInfo2 *pinfo2,
2594 TALLOC_CTX *mem_ctx)
2596 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2599 /*******************************************************************
2600 * fill a notify_info_data with the printername
2601 * but it doesn't exist, have to see what to do
2602 ********************************************************************/
2604 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2605 int snum,
2606 struct spoolss_Notify *data,
2607 print_queue_struct *queue,
2608 struct spoolss_PrinterInfo2 *pinfo2,
2609 TALLOC_CTX *mem_ctx)
2611 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2614 /*******************************************************************
2615 * fill a notify_info_data with the comment
2616 ********************************************************************/
2618 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2619 int snum,
2620 struct spoolss_Notify *data,
2621 print_queue_struct *queue,
2622 struct spoolss_PrinterInfo2 *pinfo2,
2623 TALLOC_CTX *mem_ctx)
2625 const char *p;
2627 if (*pinfo2->comment == '\0') {
2628 p = lp_comment(snum);
2629 } else {
2630 p = pinfo2->comment;
2633 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2636 /*******************************************************************
2637 * fill a notify_info_data with the comment
2638 * location = "Room 1, floor 2, building 3"
2639 ********************************************************************/
2641 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2642 int snum,
2643 struct spoolss_Notify *data,
2644 print_queue_struct *queue,
2645 struct spoolss_PrinterInfo2 *pinfo2,
2646 TALLOC_CTX *mem_ctx)
2648 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->location);
2651 /*******************************************************************
2652 * fill a notify_info_data with the device mode
2653 * jfm:xxxx don't to it for know but that's a real problem !!!
2654 ********************************************************************/
2656 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2657 int snum,
2658 struct spoolss_Notify *data,
2659 print_queue_struct *queue,
2660 struct spoolss_PrinterInfo2 *pinfo2,
2661 TALLOC_CTX *mem_ctx)
2663 /* for a dummy implementation we have to zero the fields */
2664 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2667 /*******************************************************************
2668 * fill a notify_info_data with the separator file name
2669 ********************************************************************/
2671 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2672 int snum,
2673 struct spoolss_Notify *data,
2674 print_queue_struct *queue,
2675 struct spoolss_PrinterInfo2 *pinfo2,
2676 TALLOC_CTX *mem_ctx)
2678 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2681 /*******************************************************************
2682 * fill a notify_info_data with the print processor
2683 * jfm:xxxx return always winprint to indicate we don't do anything to it
2684 ********************************************************************/
2686 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2687 int snum,
2688 struct spoolss_Notify *data,
2689 print_queue_struct *queue,
2690 struct spoolss_PrinterInfo2 *pinfo2,
2691 TALLOC_CTX *mem_ctx)
2693 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2696 /*******************************************************************
2697 * fill a notify_info_data with the print processor options
2698 * jfm:xxxx send an empty string
2699 ********************************************************************/
2701 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2702 int snum,
2703 struct spoolss_Notify *data,
2704 print_queue_struct *queue,
2705 struct spoolss_PrinterInfo2 *pinfo2,
2706 TALLOC_CTX *mem_ctx)
2708 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2711 /*******************************************************************
2712 * fill a notify_info_data with the data type
2713 * jfm:xxxx always send RAW as data type
2714 ********************************************************************/
2716 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2717 int snum,
2718 struct spoolss_Notify *data,
2719 print_queue_struct *queue,
2720 struct spoolss_PrinterInfo2 *pinfo2,
2721 TALLOC_CTX *mem_ctx)
2723 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2726 /*******************************************************************
2727 * fill a notify_info_data with the security descriptor
2728 * jfm:xxxx send an null pointer to say no security desc
2729 * have to implement security before !
2730 ********************************************************************/
2732 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2733 int snum,
2734 struct spoolss_Notify *data,
2735 print_queue_struct *queue,
2736 struct spoolss_PrinterInfo2 *pinfo2,
2737 TALLOC_CTX *mem_ctx)
2739 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
2742 /*******************************************************************
2743 * fill a notify_info_data with the attributes
2744 * jfm:xxxx a samba printer is always shared
2745 ********************************************************************/
2747 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2748 int snum,
2749 struct spoolss_Notify *data,
2750 print_queue_struct *queue,
2751 struct spoolss_PrinterInfo2 *pinfo2,
2752 TALLOC_CTX *mem_ctx)
2754 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2757 /*******************************************************************
2758 * fill a notify_info_data with the priority
2759 ********************************************************************/
2761 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
2762 int snum,
2763 struct spoolss_Notify *data,
2764 print_queue_struct *queue,
2765 struct spoolss_PrinterInfo2 *pinfo2,
2766 TALLOC_CTX *mem_ctx)
2768 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
2771 /*******************************************************************
2772 * fill a notify_info_data with the default priority
2773 ********************************************************************/
2775 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
2776 int snum,
2777 struct spoolss_Notify *data,
2778 print_queue_struct *queue,
2779 struct spoolss_PrinterInfo2 *pinfo2,
2780 TALLOC_CTX *mem_ctx)
2782 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
2785 /*******************************************************************
2786 * fill a notify_info_data with the start time
2787 ********************************************************************/
2789 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
2790 int snum,
2791 struct spoolss_Notify *data,
2792 print_queue_struct *queue,
2793 struct spoolss_PrinterInfo2 *pinfo2,
2794 TALLOC_CTX *mem_ctx)
2796 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
2799 /*******************************************************************
2800 * fill a notify_info_data with the until time
2801 ********************************************************************/
2803 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
2804 int snum,
2805 struct spoolss_Notify *data,
2806 print_queue_struct *queue,
2807 struct spoolss_PrinterInfo2 *pinfo2,
2808 TALLOC_CTX *mem_ctx)
2810 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
2813 /*******************************************************************
2814 * fill a notify_info_data with the status
2815 ********************************************************************/
2817 static void spoolss_notify_status(struct messaging_context *msg_ctx,
2818 int snum,
2819 struct spoolss_Notify *data,
2820 print_queue_struct *queue,
2821 struct spoolss_PrinterInfo2 *pinfo2,
2822 TALLOC_CTX *mem_ctx)
2824 print_status_struct status;
2826 print_queue_length(msg_ctx, snum, &status);
2827 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
2830 /*******************************************************************
2831 * fill a notify_info_data with the number of jobs queued
2832 ********************************************************************/
2834 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
2835 int snum,
2836 struct spoolss_Notify *data,
2837 print_queue_struct *queue,
2838 struct spoolss_PrinterInfo2 *pinfo2,
2839 TALLOC_CTX *mem_ctx)
2841 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
2842 data, print_queue_length(msg_ctx, snum, NULL));
2845 /*******************************************************************
2846 * fill a notify_info_data with the average ppm
2847 ********************************************************************/
2849 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
2850 int snum,
2851 struct spoolss_Notify *data,
2852 print_queue_struct *queue,
2853 struct spoolss_PrinterInfo2 *pinfo2,
2854 TALLOC_CTX *mem_ctx)
2856 /* always respond 8 pages per minutes */
2857 /* a little hard ! */
2858 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
2861 /*******************************************************************
2862 * fill a notify_info_data with username
2863 ********************************************************************/
2865 static void spoolss_notify_username(struct messaging_context *msg_ctx,
2866 int snum,
2867 struct spoolss_Notify *data,
2868 print_queue_struct *queue,
2869 struct spoolss_PrinterInfo2 *pinfo2,
2870 TALLOC_CTX *mem_ctx)
2872 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
2875 /*******************************************************************
2876 * fill a notify_info_data with job status
2877 ********************************************************************/
2879 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
2880 int snum,
2881 struct spoolss_Notify *data,
2882 print_queue_struct *queue,
2883 struct spoolss_PrinterInfo2 *pinfo2,
2884 TALLOC_CTX *mem_ctx)
2886 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
2889 /*******************************************************************
2890 * fill a notify_info_data with job name
2891 ********************************************************************/
2893 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
2894 int snum,
2895 struct spoolss_Notify *data,
2896 print_queue_struct *queue,
2897 struct spoolss_PrinterInfo2 *pinfo2,
2898 TALLOC_CTX *mem_ctx)
2900 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
2903 /*******************************************************************
2904 * fill a notify_info_data with job status
2905 ********************************************************************/
2907 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
2908 int snum,
2909 struct spoolss_Notify *data,
2910 print_queue_struct *queue,
2911 struct spoolss_PrinterInfo2 *pinfo2,
2912 TALLOC_CTX *mem_ctx)
2915 * Now we're returning job status codes we just return a "" here. JRA.
2918 const char *p = "";
2920 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
2921 p = "unknown";
2923 switch (queue->status) {
2924 case LPQ_QUEUED:
2925 p = "Queued";
2926 break;
2927 case LPQ_PAUSED:
2928 p = ""; /* NT provides the paused string */
2929 break;
2930 case LPQ_SPOOLING:
2931 p = "Spooling";
2932 break;
2933 case LPQ_PRINTING:
2934 p = "Printing";
2935 break;
2937 #endif /* NO LONGER NEEDED. */
2939 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2942 /*******************************************************************
2943 * fill a notify_info_data with job time
2944 ********************************************************************/
2946 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
2947 int snum,
2948 struct spoolss_Notify *data,
2949 print_queue_struct *queue,
2950 struct spoolss_PrinterInfo2 *pinfo2,
2951 TALLOC_CTX *mem_ctx)
2953 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
2956 /*******************************************************************
2957 * fill a notify_info_data with job size
2958 ********************************************************************/
2960 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
2961 int snum,
2962 struct spoolss_Notify *data,
2963 print_queue_struct *queue,
2964 struct spoolss_PrinterInfo2 *pinfo2,
2965 TALLOC_CTX *mem_ctx)
2967 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
2970 /*******************************************************************
2971 * fill a notify_info_data with page info
2972 ********************************************************************/
2973 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
2974 int snum,
2975 struct spoolss_Notify *data,
2976 print_queue_struct *queue,
2977 struct spoolss_PrinterInfo2 *pinfo2,
2978 TALLOC_CTX *mem_ctx)
2980 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
2983 /*******************************************************************
2984 * fill a notify_info_data with pages printed info.
2985 ********************************************************************/
2986 static void spoolss_notify_pages_printed(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 /* Add code when back-end tracks this */
2994 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
2997 /*******************************************************************
2998 Fill a notify_info_data with job position.
2999 ********************************************************************/
3001 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3002 int snum,
3003 struct spoolss_Notify *data,
3004 print_queue_struct *queue,
3005 struct spoolss_PrinterInfo2 *pinfo2,
3006 TALLOC_CTX *mem_ctx)
3008 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3011 /*******************************************************************
3012 Fill a notify_info_data with submitted time.
3013 ********************************************************************/
3015 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3016 int snum,
3017 struct spoolss_Notify *data,
3018 print_queue_struct *queue,
3019 struct spoolss_PrinterInfo2 *pinfo2,
3020 TALLOC_CTX *mem_ctx)
3022 data->data.string.string = NULL;
3023 data->data.string.size = 0;
3025 init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3026 &data->data.string.string,
3027 &data->data.string.size);
3031 struct s_notify_info_data_table
3033 enum spoolss_NotifyType type;
3034 uint16_t field;
3035 const char *name;
3036 enum spoolss_NotifyTable variable_type;
3037 void (*fn) (struct messaging_context *msg_ctx,
3038 int snum, struct spoolss_Notify *data,
3039 print_queue_struct *queue,
3040 struct spoolss_PrinterInfo2 *pinfo2,
3041 TALLOC_CTX *mem_ctx);
3044 /* A table describing the various print notification constants and
3045 whether the notification data is a pointer to a variable sized
3046 buffer, a one value uint32_t or a two value uint32_t. */
3048 static const struct s_notify_info_data_table notify_info_data_table[] =
3050 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3051 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3052 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
3053 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3054 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3055 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
3056 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
3057 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3058 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
3059 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3060 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3061 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3062 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
3063 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
3064 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3065 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
3066 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3067 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3068 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
3069 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
3070 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
3071 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
3072 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
3073 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3074 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
3075 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3076 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINTER_NAME, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3077 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_MACHINE_NAME, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3078 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PORT_NAME, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3079 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_USER_NAME, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3080 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_NOTIFY_NAME, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3081 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DATATYPE, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3082 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINT_PROCESSOR, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3083 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PARAMETERS, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3084 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DRIVER_NAME, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3085 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DEVMODE, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3086 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
3087 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS_STRING, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
3088 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
3089 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DOCUMENT, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
3090 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRIORITY, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3091 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_POSITION, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
3092 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SUBMITTED, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
3093 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_START_TIME, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3094 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_UNTIL_TIME, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3095 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TIME, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
3096 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_PAGES, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
3097 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PAGES_PRINTED, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
3098 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_BYTES, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
3101 /*******************************************************************
3102 Return the variable_type of info_data structure.
3103 ********************************************************************/
3105 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3106 uint16_t field)
3108 int i=0;
3110 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3111 if ( (notify_info_data_table[i].type == type) &&
3112 (notify_info_data_table[i].field == field) ) {
3113 return notify_info_data_table[i].variable_type;
3117 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3119 return (enum spoolss_NotifyTable) 0;
3122 /****************************************************************************
3123 ****************************************************************************/
3125 static bool search_notify(enum spoolss_NotifyType type,
3126 uint16_t field,
3127 int *value)
3129 int i;
3131 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3132 if (notify_info_data_table[i].type == type &&
3133 notify_info_data_table[i].field == field &&
3134 notify_info_data_table[i].fn != NULL) {
3135 *value = i;
3136 return true;
3140 return false;
3143 /****************************************************************************
3144 ****************************************************************************/
3146 static void construct_info_data(struct spoolss_Notify *info_data,
3147 enum spoolss_NotifyType type,
3148 uint16_t field, int id)
3150 info_data->type = type;
3151 info_data->field.field = field;
3152 info_data->variable_type = variable_type_of_notify_info_data(type, field);
3153 info_data->job_id = id;
3156 /*******************************************************************
3158 * fill a notify_info struct with info asked
3160 ********************************************************************/
3162 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3163 Printer_entry *print_hnd,
3164 struct spoolss_NotifyInfo *info,
3165 struct spoolss_PrinterInfo2 *pinfo2,
3166 int snum,
3167 const struct spoolss_NotifyOptionType *option_type,
3168 uint32_t id,
3169 TALLOC_CTX *mem_ctx)
3171 int field_num,j;
3172 enum spoolss_NotifyType type;
3173 uint16_t field;
3175 struct spoolss_Notify *current_data;
3176 print_queue_struct *queue=NULL;
3178 type = option_type->type;
3180 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3181 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3182 option_type->count, lp_servicename(snum)));
3184 for(field_num=0; field_num < option_type->count; field_num++) {
3185 field = option_type->fields[field_num].field;
3187 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3189 if (!search_notify(type, field, &j) )
3190 continue;
3192 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3193 struct spoolss_Notify,
3194 info->count + 1);
3195 if (info->notifies == NULL) {
3196 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3197 return false;
3200 current_data = &info->notifies[info->count];
3202 construct_info_data(current_data, type, field, id);
3204 DEBUG(10, ("construct_notify_printer_info: "
3205 "calling [%s] snum=%d printername=[%s])\n",
3206 notify_info_data_table[j].name, snum,
3207 pinfo2->printername));
3209 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3210 queue, pinfo2, mem_ctx);
3212 info->count++;
3215 return true;
3218 /*******************************************************************
3220 * fill a notify_info struct with info asked
3222 ********************************************************************/
3224 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3225 print_queue_struct *queue,
3226 struct spoolss_NotifyInfo *info,
3227 struct spoolss_PrinterInfo2 *pinfo2,
3228 int snum,
3229 const struct spoolss_NotifyOptionType *option_type,
3230 uint32_t id,
3231 TALLOC_CTX *mem_ctx)
3233 int field_num,j;
3234 enum spoolss_NotifyType type;
3235 uint16_t field;
3236 struct spoolss_Notify *current_data;
3238 DEBUG(4,("construct_notify_jobs_info\n"));
3240 type = option_type->type;
3242 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3243 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3244 option_type->count));
3246 for(field_num=0; field_num<option_type->count; field_num++) {
3247 field = option_type->fields[field_num].field;
3249 if (!search_notify(type, field, &j) )
3250 continue;
3252 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3253 struct spoolss_Notify,
3254 info->count + 1);
3255 if (info->notifies == NULL) {
3256 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3257 return false;
3260 current_data=&(info->notifies[info->count]);
3262 construct_info_data(current_data, type, field, id);
3263 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3264 queue, pinfo2, mem_ctx);
3265 info->count++;
3268 return true;
3272 * JFM: The enumeration is not that simple, it's even non obvious.
3274 * let's take an example: I want to monitor the PRINTER SERVER for
3275 * the printer's name and the number of jobs currently queued.
3276 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3277 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3279 * I have 3 printers on the back of my server.
3281 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3282 * structures.
3283 * Number Data Id
3284 * 1 printer 1 name 1
3285 * 2 printer 1 cjob 1
3286 * 3 printer 2 name 2
3287 * 4 printer 2 cjob 2
3288 * 5 printer 3 name 3
3289 * 6 printer 3 name 3
3291 * that's the print server case, the printer case is even worse.
3294 /*******************************************************************
3296 * enumerate all printers on the printserver
3297 * fill a notify_info struct with info asked
3299 ********************************************************************/
3301 static WERROR printserver_notify_info(struct pipes_struct *p,
3302 struct policy_handle *hnd,
3303 struct spoolss_NotifyInfo *info,
3304 TALLOC_CTX *mem_ctx)
3306 int snum;
3307 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3308 int n_services=lp_numservices();
3309 int i;
3310 struct spoolss_NotifyOption *option;
3311 struct spoolss_NotifyOptionType option_type;
3312 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3313 WERROR result;
3315 DEBUG(4,("printserver_notify_info\n"));
3317 if (!Printer)
3318 return WERR_BADFID;
3320 option = Printer->notify.option;
3322 info->version = 2;
3323 info->notifies = NULL;
3324 info->count = 0;
3326 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3327 sending a ffpcn() request first */
3329 if ( !option )
3330 return WERR_BADFID;
3332 for (i=0; i<option->count; i++) {
3333 option_type = option->types[i];
3335 if (option_type.type != PRINTER_NOTIFY_TYPE)
3336 continue;
3338 for (snum = 0; snum < n_services; snum++) {
3339 if (!lp_browseable(snum) ||
3340 !lp_snum_ok(snum) ||
3341 !lp_print_ok(snum)) {
3342 continue; /* skip */
3345 /* Maybe we should use the SYSTEM server_info here... */
3346 result = winreg_get_printer(mem_ctx, p->server_info,
3347 p->msg_ctx,
3348 Printer->servername,
3349 lp_servicename(snum),
3350 &pinfo2);
3351 if (!W_ERROR_IS_OK(result)) {
3352 DEBUG(4, ("printserver_notify_info: "
3353 "Failed to get printer [%s]\n",
3354 lp_servicename(snum)));
3355 continue;
3359 construct_notify_printer_info(p->msg_ctx,
3360 Printer, info,
3361 pinfo2, snum,
3362 &option_type, snum,
3363 mem_ctx);
3365 TALLOC_FREE(pinfo2);
3369 #if 0
3371 * Debugging information, don't delete.
3374 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3375 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3376 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3378 for (i=0; i<info->count; i++) {
3379 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3380 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3381 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3383 #endif
3385 return WERR_OK;
3388 /*******************************************************************
3390 * fill a notify_info struct with info asked
3392 ********************************************************************/
3394 static WERROR printer_notify_info(struct pipes_struct *p,
3395 struct policy_handle *hnd,
3396 struct spoolss_NotifyInfo *info,
3397 TALLOC_CTX *mem_ctx)
3399 int snum;
3400 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3401 int i;
3402 uint32_t id;
3403 struct spoolss_NotifyOption *option;
3404 struct spoolss_NotifyOptionType option_type;
3405 int count,j;
3406 print_queue_struct *queue=NULL;
3407 print_status_struct status;
3408 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3409 WERROR result;
3411 DEBUG(4,("printer_notify_info\n"));
3413 if (!Printer)
3414 return WERR_BADFID;
3416 option = Printer->notify.option;
3417 id = 0x0;
3419 info->version = 2;
3420 info->notifies = NULL;
3421 info->count = 0;
3423 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3424 sending a ffpcn() request first */
3426 if ( !option )
3427 return WERR_BADFID;
3429 get_printer_snum(p, hnd, &snum, NULL);
3431 /* Maybe we should use the SYSTEM server_info here... */
3432 result = winreg_get_printer(mem_ctx, p->server_info, p->msg_ctx,
3433 Printer->servername,
3434 lp_servicename(snum), &pinfo2);
3435 if (!W_ERROR_IS_OK(result)) {
3436 return WERR_BADFID;
3439 for (i=0; i<option->count; i++) {
3440 option_type = option->types[i];
3442 switch (option_type.type) {
3443 case PRINTER_NOTIFY_TYPE:
3444 if (construct_notify_printer_info(p->msg_ctx,
3445 Printer, info,
3446 pinfo2, snum,
3447 &option_type, id,
3448 mem_ctx)) {
3449 id--;
3451 break;
3453 case JOB_NOTIFY_TYPE:
3455 count = print_queue_status(p->msg_ctx, snum, &queue,
3456 &status);
3458 for (j=0; j<count; j++) {
3459 construct_notify_jobs_info(p->msg_ctx,
3460 &queue[j], info,
3461 pinfo2, snum,
3462 &option_type,
3463 queue[j].job,
3464 mem_ctx);
3467 SAFE_FREE(queue);
3468 break;
3473 * Debugging information, don't delete.
3476 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3477 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3478 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3480 for (i=0; i<info->count; i++) {
3481 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3482 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3483 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3487 talloc_free(pinfo2);
3488 return WERR_OK;
3491 /****************************************************************
3492 _spoolss_RouterRefreshPrinterChangeNotify
3493 ****************************************************************/
3495 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3496 struct spoolss_RouterRefreshPrinterChangeNotify *r)
3498 struct spoolss_NotifyInfo *info;
3500 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
3501 WERROR result = WERR_BADFID;
3503 /* we always have a spoolss_NotifyInfo struct */
3504 info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3505 if (!info) {
3506 result = WERR_NOMEM;
3507 goto done;
3510 *r->out.info = info;
3512 if (!Printer) {
3513 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3514 "Invalid handle (%s:%u:%u).\n",
3515 OUR_HANDLE(r->in.handle)));
3516 goto done;
3519 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3522 * We are now using the change value, and
3523 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3524 * I don't have a global notification system, I'm sending back all the
3525 * informations even when _NOTHING_ has changed.
3528 /* We need to keep track of the change value to send back in
3529 RRPCN replies otherwise our updates are ignored. */
3531 Printer->notify.fnpcn = true;
3533 if (Printer->notify.client_connected) {
3534 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3535 "Saving change value in request [%x]\n",
3536 r->in.change_low));
3537 Printer->notify.change = r->in.change_low;
3540 /* just ignore the spoolss_NotifyOption */
3542 switch (Printer->printer_type) {
3543 case SPLHND_SERVER:
3544 result = printserver_notify_info(p, r->in.handle,
3545 info, p->mem_ctx);
3546 break;
3548 case SPLHND_PRINTER:
3549 result = printer_notify_info(p, r->in.handle,
3550 info, p->mem_ctx);
3551 break;
3554 Printer->notify.fnpcn = false;
3556 done:
3557 return result;
3560 /********************************************************************
3561 * construct_printer_info_0
3562 * fill a printer_info_0 struct
3563 ********************************************************************/
3565 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3566 struct auth_serversupplied_info *server_info,
3567 struct messaging_context *msg_ctx,
3568 struct spoolss_PrinterInfo2 *info2,
3569 struct spoolss_PrinterInfo0 *r,
3570 int snum)
3572 int count;
3573 counter_printer_0 *session_counter;
3574 struct timeval setuptime;
3575 print_status_struct status;
3577 r->printername = talloc_strdup(mem_ctx, info2->printername);
3578 W_ERROR_HAVE_NO_MEMORY(r->printername);
3580 r->servername = talloc_strdup(mem_ctx, info2->servername);
3581 W_ERROR_HAVE_NO_MEMORY(r->servername);
3583 count = print_queue_length(msg_ctx, snum, &status);
3585 /* check if we already have a counter for this printer */
3586 for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3587 if (session_counter->snum == snum)
3588 break;
3591 /* it's the first time, add it to the list */
3592 if (session_counter == NULL) {
3593 session_counter = SMB_MALLOC_P(counter_printer_0);
3594 W_ERROR_HAVE_NO_MEMORY(session_counter);
3595 ZERO_STRUCTP(session_counter);
3596 session_counter->snum = snum;
3597 session_counter->counter = 0;
3598 DLIST_ADD(counter_list, session_counter);
3601 /* increment it */
3602 session_counter->counter++;
3604 r->cjobs = count;
3605 r->total_jobs = 0;
3606 r->total_bytes = 0;
3608 get_startup_time(&setuptime);
3609 init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3611 /* JFM:
3612 * the global_counter should be stored in a TDB as it's common to all the clients
3613 * and should be zeroed on samba startup
3615 r->global_counter = session_counter->counter;
3616 r->total_pages = 0;
3617 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3618 SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3619 SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3620 r->free_build = SPOOLSS_RELEASE_BUILD;
3621 r->spooling = 0;
3622 r->max_spooling = 0;
3623 r->session_counter = session_counter->counter;
3624 r->num_error_out_of_paper = 0x0;
3625 r->num_error_not_ready = 0x0; /* number of print failure */
3626 r->job_error = 0x0;
3627 r->number_of_processors = 0x1;
3628 r->processor_type = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3629 r->high_part_total_bytes = 0x0;
3631 /* ChangeID in milliseconds*/
3632 winreg_printer_get_changeid(mem_ctx, server_info, msg_ctx,
3633 info2->sharename, &r->change_id);
3635 r->last_error = WERR_OK;
3636 r->status = nt_printq_status(status.status);
3637 r->enumerate_network_printers = 0x0;
3638 r->c_setprinter = 0x0;
3639 r->processor_architecture = PROCESSOR_ARCHITECTURE_INTEL;
3640 r->processor_level = 0x6; /* 6 ???*/
3641 r->ref_ic = 0;
3642 r->reserved2 = 0;
3643 r->reserved3 = 0;
3645 return WERR_OK;
3649 /********************************************************************
3650 * construct_printer_info1
3651 * fill a spoolss_PrinterInfo1 struct
3652 ********************************************************************/
3654 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3655 const struct spoolss_PrinterInfo2 *info2,
3656 uint32_t flags,
3657 struct spoolss_PrinterInfo1 *r,
3658 int snum)
3660 r->flags = flags;
3662 r->description = talloc_asprintf(mem_ctx, "%s,%s,%s",
3663 info2->printername,
3664 info2->drivername,
3665 info2->location);
3666 W_ERROR_HAVE_NO_MEMORY(r->description);
3668 if (info2->comment == NULL || info2->comment[0] == '\0') {
3669 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
3670 } else {
3671 r->comment = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3673 W_ERROR_HAVE_NO_MEMORY(r->comment);
3675 r->name = talloc_strdup(mem_ctx, info2->printername);
3676 W_ERROR_HAVE_NO_MEMORY(r->name);
3678 return WERR_OK;
3681 /********************************************************************
3682 * construct_printer_info2
3683 * fill a spoolss_PrinterInfo2 struct
3684 ********************************************************************/
3686 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3687 struct messaging_context *msg_ctx,
3688 const struct spoolss_PrinterInfo2 *info2,
3689 struct spoolss_PrinterInfo2 *r,
3690 int snum)
3692 int count;
3693 print_status_struct status;
3695 count = print_queue_length(msg_ctx, snum, &status);
3697 r->servername = talloc_strdup(mem_ctx, info2->servername);
3698 W_ERROR_HAVE_NO_MEMORY(r->servername);
3699 r->printername = talloc_strdup(mem_ctx, info2->printername);
3700 W_ERROR_HAVE_NO_MEMORY(r->printername);
3701 r->sharename = talloc_strdup(mem_ctx, lp_servicename(snum));
3702 W_ERROR_HAVE_NO_MEMORY(r->sharename);
3703 r->portname = talloc_strdup(mem_ctx, info2->portname);
3704 W_ERROR_HAVE_NO_MEMORY(r->portname);
3705 r->drivername = talloc_strdup(mem_ctx, info2->drivername);
3706 W_ERROR_HAVE_NO_MEMORY(r->drivername);
3708 if (info2->comment[0] == '\0') {
3709 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
3710 } else {
3711 r->comment = talloc_strdup(mem_ctx, info2->comment);
3713 W_ERROR_HAVE_NO_MEMORY(r->comment);
3715 r->location = talloc_strdup(mem_ctx, info2->location);
3716 W_ERROR_HAVE_NO_MEMORY(r->location);
3717 r->sepfile = talloc_strdup(mem_ctx, info2->sepfile);
3718 W_ERROR_HAVE_NO_MEMORY(r->sepfile);
3719 r->printprocessor = talloc_strdup(mem_ctx, info2->printprocessor);
3720 W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
3721 r->datatype = talloc_strdup(mem_ctx, info2->datatype);
3722 W_ERROR_HAVE_NO_MEMORY(r->datatype);
3723 r->parameters = talloc_strdup(mem_ctx, info2->parameters);
3724 W_ERROR_HAVE_NO_MEMORY(r->parameters);
3726 r->attributes = info2->attributes;
3728 r->priority = info2->priority;
3729 r->defaultpriority = info2->defaultpriority;
3730 r->starttime = info2->starttime;
3731 r->untiltime = info2->untiltime;
3732 r->status = nt_printq_status(status.status);
3733 r->cjobs = count;
3734 r->averageppm = info2->averageppm;
3736 copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
3737 if (!r->devmode) {
3738 DEBUG(8,("Returning NULL Devicemode!\n"));
3741 r->secdesc = NULL;
3743 if (info2->secdesc != NULL) {
3744 /* don't use talloc_steal() here unless you do a deep steal of all
3745 the SEC_DESC members */
3747 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
3750 return WERR_OK;
3753 /********************************************************************
3754 * construct_printer_info3
3755 * fill a spoolss_PrinterInfo3 struct
3756 ********************************************************************/
3758 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
3759 const struct spoolss_PrinterInfo2 *info2,
3760 struct spoolss_PrinterInfo3 *r,
3761 int snum)
3763 /* These are the components of the SD we are returning. */
3765 if (info2->secdesc != NULL) {
3766 /* don't use talloc_steal() here unless you do a deep steal of all
3767 the SEC_DESC members */
3769 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
3770 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
3773 return WERR_OK;
3776 /********************************************************************
3777 * construct_printer_info4
3778 * fill a spoolss_PrinterInfo4 struct
3779 ********************************************************************/
3781 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
3782 const struct spoolss_PrinterInfo2 *info2,
3783 struct spoolss_PrinterInfo4 *r,
3784 int snum)
3786 r->printername = talloc_strdup(mem_ctx, info2->printername);
3787 W_ERROR_HAVE_NO_MEMORY(r->printername);
3788 r->servername = talloc_strdup(mem_ctx, info2->servername);
3789 W_ERROR_HAVE_NO_MEMORY(r->servername);
3791 r->attributes = info2->attributes;
3793 return WERR_OK;
3796 /********************************************************************
3797 * construct_printer_info5
3798 * fill a spoolss_PrinterInfo5 struct
3799 ********************************************************************/
3801 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
3802 const struct spoolss_PrinterInfo2 *info2,
3803 struct spoolss_PrinterInfo5 *r,
3804 int snum)
3806 r->printername = talloc_strdup(mem_ctx, info2->printername);
3807 W_ERROR_HAVE_NO_MEMORY(r->printername);
3808 r->portname = talloc_strdup(mem_ctx, info2->portname);
3809 W_ERROR_HAVE_NO_MEMORY(r->portname);
3811 r->attributes = info2->attributes;
3813 /* these two are not used by NT+ according to MSDN */
3814 r->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
3815 r->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
3817 return WERR_OK;
3820 /********************************************************************
3821 * construct_printer_info_6
3822 * fill a spoolss_PrinterInfo6 struct
3823 ********************************************************************/
3825 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
3826 struct messaging_context *msg_ctx,
3827 const struct spoolss_PrinterInfo2 *info2,
3828 struct spoolss_PrinterInfo6 *r,
3829 int snum)
3831 int count;
3832 print_status_struct status;
3834 count = print_queue_length(msg_ctx, snum, &status);
3836 r->status = nt_printq_status(status.status);
3838 return WERR_OK;
3841 /********************************************************************
3842 * construct_printer_info7
3843 * fill a spoolss_PrinterInfo7 struct
3844 ********************************************************************/
3846 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
3847 struct messaging_context *msg_ctx,
3848 Printer_entry *print_hnd,
3849 struct spoolss_PrinterInfo7 *r,
3850 int snum)
3852 struct auth_serversupplied_info *server_info;
3853 struct GUID guid;
3854 NTSTATUS status;
3856 status = make_server_info_system(mem_ctx, &server_info);
3857 if (!NT_STATUS_IS_OK(status)) {
3858 DEBUG(0, ("construct_printer_info7: "
3859 "Could not create system server_info\n"));
3860 return WERR_NOMEM;
3863 if (is_printer_published(mem_ctx, server_info, msg_ctx,
3864 print_hnd->servername,
3865 lp_servicename(snum), &guid, NULL)) {
3866 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
3867 r->action = DSPRINT_PUBLISH;
3868 } else {
3869 r->guid = talloc_strdup(mem_ctx, "");
3870 r->action = DSPRINT_UNPUBLISH;
3872 W_ERROR_HAVE_NO_MEMORY(r->guid);
3874 TALLOC_FREE(server_info);
3875 return WERR_OK;
3878 /********************************************************************
3879 * construct_printer_info8
3880 * fill a spoolss_PrinterInfo8 struct
3881 ********************************************************************/
3883 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
3884 const struct spoolss_PrinterInfo2 *info2,
3885 struct spoolss_DeviceModeInfo *r,
3886 int snum)
3888 copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
3889 if (!r->devmode) {
3890 DEBUG(8,("Returning NULL Devicemode!\n"));
3893 return WERR_OK;
3897 /********************************************************************
3898 ********************************************************************/
3900 static bool snum_is_shared_printer(int snum)
3902 return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
3905 /********************************************************************
3906 Spoolss_enumprinters.
3907 ********************************************************************/
3909 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
3910 struct auth_serversupplied_info *server_info,
3911 struct messaging_context *msg_ctx,
3912 uint32_t level,
3913 uint32_t flags,
3914 union spoolss_PrinterInfo **info_p,
3915 uint32_t *count_p)
3917 int snum;
3918 int n_services = lp_numservices();
3919 union spoolss_PrinterInfo *info = NULL;
3920 uint32_t count = 0;
3921 WERROR result = WERR_OK;
3923 *count_p = 0;
3924 *info_p = NULL;
3926 for (snum = 0; snum < n_services; snum++) {
3928 const char *printer;
3929 struct spoolss_PrinterInfo2 *info2;
3931 if (!snum_is_shared_printer(snum)) {
3932 continue;
3935 printer = lp_const_servicename(snum);
3937 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
3938 printer, snum));
3940 result = winreg_create_printer(mem_ctx,
3941 server_info,
3942 msg_ctx,
3943 NULL,
3944 printer);
3945 if (!W_ERROR_IS_OK(result)) {
3946 goto out;
3949 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
3950 union spoolss_PrinterInfo,
3951 count + 1);
3952 if (!info) {
3953 result = WERR_NOMEM;
3954 goto out;
3957 result = winreg_get_printer(mem_ctx, server_info, msg_ctx,
3958 NULL, printer, &info2);
3959 if (!W_ERROR_IS_OK(result)) {
3960 goto out;
3963 switch (level) {
3964 case 0:
3965 result = construct_printer_info0(info, server_info,
3966 msg_ctx, info2,
3967 &info[count].info0, snum);
3968 break;
3969 case 1:
3970 result = construct_printer_info1(info, info2, flags,
3971 &info[count].info1, snum);
3972 break;
3973 case 2:
3974 result = construct_printer_info2(info, msg_ctx, info2,
3975 &info[count].info2, snum);
3976 break;
3977 case 4:
3978 result = construct_printer_info4(info, info2,
3979 &info[count].info4, snum);
3980 break;
3981 case 5:
3982 result = construct_printer_info5(info, info2,
3983 &info[count].info5, snum);
3984 break;
3986 default:
3987 result = WERR_UNKNOWN_LEVEL;
3988 goto out;
3991 if (!W_ERROR_IS_OK(result)) {
3992 goto out;
3995 count++;
3998 *count_p = count;
3999 *info_p = info;
4001 out:
4002 if (!W_ERROR_IS_OK(result)) {
4003 TALLOC_FREE(info);
4004 return result;
4007 *info_p = info;
4009 return WERR_OK;
4012 /********************************************************************
4013 * handle enumeration of printers at level 0
4014 ********************************************************************/
4016 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4017 struct auth_serversupplied_info *server_info,
4018 struct messaging_context *msg_ctx,
4019 uint32_t flags,
4020 const char *servername,
4021 union spoolss_PrinterInfo **info,
4022 uint32_t *count)
4024 DEBUG(4,("enum_all_printers_info_0\n"));
4026 return enum_all_printers_info_level(mem_ctx, server_info, msg_ctx,
4027 0, flags, info, count);
4031 /********************************************************************
4032 ********************************************************************/
4034 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4035 struct auth_serversupplied_info *server_info,
4036 struct messaging_context *msg_ctx,
4037 uint32_t flags,
4038 union spoolss_PrinterInfo **info,
4039 uint32_t *count)
4041 DEBUG(4,("enum_all_printers_info_1\n"));
4043 return enum_all_printers_info_level(mem_ctx, server_info, msg_ctx,
4044 1, flags, info, count);
4047 /********************************************************************
4048 enum_all_printers_info_1_local.
4049 *********************************************************************/
4051 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4052 struct auth_serversupplied_info *server_info,
4053 struct messaging_context *msg_ctx,
4054 union spoolss_PrinterInfo **info,
4055 uint32_t *count)
4057 DEBUG(4,("enum_all_printers_info_1_local\n"));
4059 return enum_all_printers_info_1(mem_ctx, server_info, msg_ctx,
4060 PRINTER_ENUM_ICON8, info, count);
4063 /********************************************************************
4064 enum_all_printers_info_1_name.
4065 *********************************************************************/
4067 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4068 struct auth_serversupplied_info *server_info,
4069 struct messaging_context *msg_ctx,
4070 const char *name,
4071 union spoolss_PrinterInfo **info,
4072 uint32_t *count)
4074 const char *s = name;
4076 DEBUG(4,("enum_all_printers_info_1_name\n"));
4078 if ((name[0] == '\\') && (name[1] == '\\')) {
4079 s = name + 2;
4082 if (!is_myname_or_ipaddr(s)) {
4083 return WERR_INVALID_NAME;
4086 return enum_all_printers_info_1(mem_ctx, server_info, msg_ctx,
4087 PRINTER_ENUM_ICON8, info, count);
4090 /********************************************************************
4091 enum_all_printers_info_1_network.
4092 *********************************************************************/
4094 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4095 struct auth_serversupplied_info *server_info,
4096 struct messaging_context *msg_ctx,
4097 const char *name,
4098 union spoolss_PrinterInfo **info,
4099 uint32_t *count)
4101 const char *s = name;
4103 DEBUG(4,("enum_all_printers_info_1_network\n"));
4105 /* If we respond to a enum_printers level 1 on our name with flags
4106 set to PRINTER_ENUM_REMOTE with a list of printers then these
4107 printers incorrectly appear in the APW browse list.
4108 Specifically the printers for the server appear at the workgroup
4109 level where all the other servers in the domain are
4110 listed. Windows responds to this call with a
4111 WERR_CAN_NOT_COMPLETE so we should do the same. */
4113 if (name[0] == '\\' && name[1] == '\\') {
4114 s = name + 2;
4117 if (is_myname_or_ipaddr(s)) {
4118 return WERR_CAN_NOT_COMPLETE;
4121 return enum_all_printers_info_1(mem_ctx, server_info, msg_ctx,
4122 PRINTER_ENUM_NAME, info, count);
4125 /********************************************************************
4126 * api_spoolss_enumprinters
4128 * called from api_spoolss_enumprinters (see this to understand)
4129 ********************************************************************/
4131 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4132 struct auth_serversupplied_info *server_info,
4133 struct messaging_context *msg_ctx,
4134 union spoolss_PrinterInfo **info,
4135 uint32_t *count)
4137 DEBUG(4,("enum_all_printers_info_2\n"));
4139 return enum_all_printers_info_level(mem_ctx, server_info, msg_ctx,
4140 2, 0, info, count);
4143 /********************************************************************
4144 * handle enumeration of printers at level 1
4145 ********************************************************************/
4147 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4148 struct auth_serversupplied_info *server_info,
4149 struct messaging_context *msg_ctx,
4150 uint32_t flags,
4151 const char *name,
4152 union spoolss_PrinterInfo **info,
4153 uint32_t *count)
4155 /* Not all the flags are equals */
4157 if (flags & PRINTER_ENUM_LOCAL) {
4158 return enum_all_printers_info_1_local(mem_ctx, server_info,
4159 msg_ctx, info, count);
4162 if (flags & PRINTER_ENUM_NAME) {
4163 return enum_all_printers_info_1_name(mem_ctx, server_info,
4164 msg_ctx, name, info,
4165 count);
4168 if (flags & PRINTER_ENUM_NETWORK) {
4169 return enum_all_printers_info_1_network(mem_ctx, server_info,
4170 msg_ctx, name, info,
4171 count);
4174 return WERR_OK; /* NT4sp5 does that */
4177 /********************************************************************
4178 * handle enumeration of printers at level 2
4179 ********************************************************************/
4181 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4182 struct auth_serversupplied_info *server_info,
4183 struct messaging_context *msg_ctx,
4184 uint32_t flags,
4185 const char *servername,
4186 union spoolss_PrinterInfo **info,
4187 uint32_t *count)
4189 if (flags & PRINTER_ENUM_LOCAL) {
4190 return enum_all_printers_info_2(mem_ctx, server_info, msg_ctx,
4191 info, count);
4194 if (flags & PRINTER_ENUM_NAME) {
4195 if (!is_myname_or_ipaddr(canon_servername(servername))) {
4196 return WERR_INVALID_NAME;
4199 return enum_all_printers_info_2(mem_ctx, server_info, msg_ctx,
4200 info, count);
4203 if (flags & PRINTER_ENUM_REMOTE) {
4204 return WERR_UNKNOWN_LEVEL;
4207 return WERR_OK;
4210 /********************************************************************
4211 * handle enumeration of printers at level 4
4212 ********************************************************************/
4214 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4215 struct auth_serversupplied_info *server_info,
4216 struct messaging_context *msg_ctx,
4217 uint32_t flags,
4218 const char *servername,
4219 union spoolss_PrinterInfo **info,
4220 uint32_t *count)
4222 DEBUG(4,("enum_all_printers_info_4\n"));
4224 return enum_all_printers_info_level(mem_ctx, server_info, msg_ctx,
4225 4, flags, info, count);
4229 /********************************************************************
4230 * handle enumeration of printers at level 5
4231 ********************************************************************/
4233 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4234 struct auth_serversupplied_info *server_info,
4235 struct messaging_context *msg_ctx,
4236 uint32_t flags,
4237 const char *servername,
4238 union spoolss_PrinterInfo **info,
4239 uint32_t *count)
4241 DEBUG(4,("enum_all_printers_info_5\n"));
4243 return enum_all_printers_info_level(mem_ctx, server_info, msg_ctx,
4244 5, flags, info, count);
4247 /****************************************************************
4248 _spoolss_EnumPrinters
4249 ****************************************************************/
4251 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4252 struct spoolss_EnumPrinters *r)
4254 const char *name = NULL;
4255 WERROR result;
4257 /* that's an [in out] buffer */
4259 if (!r->in.buffer && (r->in.offered != 0)) {
4260 return WERR_INVALID_PARAM;
4263 DEBUG(4,("_spoolss_EnumPrinters\n"));
4265 *r->out.needed = 0;
4266 *r->out.count = 0;
4267 *r->out.info = NULL;
4270 * Level 1:
4271 * flags==PRINTER_ENUM_NAME
4272 * if name=="" then enumerates all printers
4273 * if name!="" then enumerate the printer
4274 * flags==PRINTER_ENUM_REMOTE
4275 * name is NULL, enumerate printers
4276 * Level 2: name!="" enumerates printers, name can't be NULL
4277 * Level 3: doesn't exist
4278 * Level 4: does a local registry lookup
4279 * Level 5: same as Level 2
4282 if (r->in.server) {
4283 name = talloc_strdup_upper(p->mem_ctx, r->in.server);
4284 W_ERROR_HAVE_NO_MEMORY(name);
4287 switch (r->in.level) {
4288 case 0:
4289 result = enumprinters_level0(p->mem_ctx, p->server_info,
4290 p->msg_ctx, r->in.flags, name,
4291 r->out.info, r->out.count);
4292 break;
4293 case 1:
4294 result = enumprinters_level1(p->mem_ctx, p->server_info,
4295 p->msg_ctx, r->in.flags, name,
4296 r->out.info, r->out.count);
4297 break;
4298 case 2:
4299 result = enumprinters_level2(p->mem_ctx, p->server_info,
4300 p->msg_ctx, r->in.flags, name,
4301 r->out.info, r->out.count);
4302 break;
4303 case 4:
4304 result = enumprinters_level4(p->mem_ctx, p->server_info,
4305 p->msg_ctx, r->in.flags, name,
4306 r->out.info, r->out.count);
4307 break;
4308 case 5:
4309 result = enumprinters_level5(p->mem_ctx, p->server_info,
4310 p->msg_ctx, r->in.flags, name,
4311 r->out.info, r->out.count);
4312 break;
4313 default:
4314 return WERR_UNKNOWN_LEVEL;
4317 if (!W_ERROR_IS_OK(result)) {
4318 return result;
4321 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4322 spoolss_EnumPrinters,
4323 *r->out.info, r->in.level,
4324 *r->out.count);
4325 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4326 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4328 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4331 /****************************************************************
4332 _spoolss_GetPrinter
4333 ****************************************************************/
4335 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4336 struct spoolss_GetPrinter *r)
4338 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
4339 struct spoolss_PrinterInfo2 *info2 = NULL;
4340 WERROR result = WERR_OK;
4341 const char *servername = NULL;
4342 int snum;
4344 /* that's an [in out] buffer */
4346 if (!r->in.buffer && (r->in.offered != 0)) {
4347 return WERR_INVALID_PARAM;
4350 *r->out.needed = 0;
4352 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4353 return WERR_BADFID;
4356 if (Printer != NULL || Printer->servername != NULL) {
4357 servername = Printer->servername;
4360 result = winreg_get_printer(p->mem_ctx,
4361 p->server_info,
4362 p->msg_ctx,
4363 servername,
4364 lp_const_servicename(snum),
4365 &info2);
4366 if (!W_ERROR_IS_OK(result)) {
4367 return result;
4370 switch (r->in.level) {
4371 case 0:
4372 result = construct_printer_info0(p->mem_ctx, p->server_info,
4373 p->msg_ctx, info2,
4374 &r->out.info->info0, snum);
4375 break;
4376 case 1:
4377 result = construct_printer_info1(p->mem_ctx, info2,
4378 PRINTER_ENUM_ICON8,
4379 &r->out.info->info1, snum);
4380 break;
4381 case 2:
4382 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4383 &r->out.info->info2, snum);
4384 break;
4385 case 3:
4386 result = construct_printer_info3(p->mem_ctx, info2,
4387 &r->out.info->info3, snum);
4388 break;
4389 case 4:
4390 result = construct_printer_info4(p->mem_ctx, info2,
4391 &r->out.info->info4, snum);
4392 break;
4393 case 5:
4394 result = construct_printer_info5(p->mem_ctx, info2,
4395 &r->out.info->info5, snum);
4396 break;
4397 case 6:
4398 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4399 &r->out.info->info6, snum);
4400 break;
4401 case 7:
4402 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4403 Printer,
4404 &r->out.info->info7, snum);
4405 break;
4406 case 8:
4407 result = construct_printer_info8(p->mem_ctx, info2,
4408 &r->out.info->info8, snum);
4409 break;
4410 default:
4411 result = WERR_UNKNOWN_LEVEL;
4412 break;
4415 if (!W_ERROR_IS_OK(result)) {
4416 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4417 r->in.level, win_errstr(result)));
4418 TALLOC_FREE(r->out.info);
4419 return result;
4422 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4423 r->out.info, r->in.level);
4424 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4426 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4429 /********************************************************************
4430 ********************************************************************/
4432 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4433 do { \
4434 if (in && strlen(in)) { \
4435 out = talloc_strdup(mem_ctx, in); \
4436 } else { \
4437 out = talloc_strdup(mem_ctx, ""); \
4439 W_ERROR_HAVE_NO_MEMORY(out); \
4440 } while (0);
4442 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4443 do { \
4444 if (in && strlen(in)) { \
4445 out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4446 } else { \
4447 out = talloc_strdup(mem_ctx, ""); \
4449 W_ERROR_HAVE_NO_MEMORY(out); \
4450 } while (0);
4452 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4453 const char **string_array,
4454 const char ***presult,
4455 const char *cservername,
4456 const char *arch,
4457 int version)
4459 int i, num_strings = 0;
4460 const char **array = NULL;
4462 if (string_array == NULL) {
4463 return WERR_INVALID_PARAMETER;;
4466 for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4467 const char *str = NULL;
4469 if (cservername == NULL || arch == NULL) {
4470 FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4471 } else {
4472 FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4475 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4476 TALLOC_FREE(array);
4477 return WERR_NOMEM;
4481 if (i > 0) {
4482 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4483 &array, &num_strings);
4486 if (presult) {
4487 *presult = array;
4490 return WERR_OK;
4493 /********************************************************************
4494 * fill a spoolss_DriverInfo1 struct
4495 ********************************************************************/
4497 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4498 struct spoolss_DriverInfo1 *r,
4499 const struct spoolss_DriverInfo8 *driver,
4500 const char *servername)
4502 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4503 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4505 return WERR_OK;
4508 /********************************************************************
4509 * fill a spoolss_DriverInfo2 struct
4510 ********************************************************************/
4512 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4513 struct spoolss_DriverInfo2 *r,
4514 const struct spoolss_DriverInfo8 *driver,
4515 const char *servername)
4518 const char *cservername = canon_servername(servername);
4520 r->version = driver->version;
4522 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4523 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4524 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4525 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4527 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4528 driver->architecture,
4529 driver->version,
4530 driver->driver_path,
4531 r->driver_path);
4533 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4534 driver->architecture,
4535 driver->version,
4536 driver->data_file,
4537 r->data_file);
4539 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4540 driver->architecture,
4541 driver->version,
4542 driver->config_file,
4543 r->config_file);
4545 return WERR_OK;
4548 /********************************************************************
4549 * fill a spoolss_DriverInfo3 struct
4550 ********************************************************************/
4552 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4553 struct spoolss_DriverInfo3 *r,
4554 const struct spoolss_DriverInfo8 *driver,
4555 const char *servername)
4557 const char *cservername = canon_servername(servername);
4559 r->version = driver->version;
4561 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4562 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4563 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4564 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4566 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4567 driver->architecture,
4568 driver->version,
4569 driver->driver_path,
4570 r->driver_path);
4572 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4573 driver->architecture,
4574 driver->version,
4575 driver->data_file,
4576 r->data_file);
4578 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4579 driver->architecture,
4580 driver->version,
4581 driver->config_file,
4582 r->config_file);
4584 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4585 driver->architecture,
4586 driver->version,
4587 driver->help_file,
4588 r->help_file);
4590 FILL_DRIVER_STRING(mem_ctx,
4591 driver->monitor_name,
4592 r->monitor_name);
4594 FILL_DRIVER_STRING(mem_ctx,
4595 driver->default_datatype,
4596 r->default_datatype);
4598 return string_array_from_driver_info(mem_ctx,
4599 driver->dependent_files,
4600 &r->dependent_files,
4601 cservername,
4602 driver->architecture,
4603 driver->version);
4606 /********************************************************************
4607 * fill a spoolss_DriverInfo4 struct
4608 ********************************************************************/
4610 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4611 struct spoolss_DriverInfo4 *r,
4612 const struct spoolss_DriverInfo8 *driver,
4613 const char *servername)
4615 const char *cservername = canon_servername(servername);
4616 WERROR result;
4618 r->version = driver->version;
4620 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4621 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4622 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4623 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4625 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4626 driver->architecture,
4627 driver->version,
4628 driver->driver_path,
4629 r->driver_path);
4631 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4632 driver->architecture,
4633 driver->version,
4634 driver->data_file,
4635 r->data_file);
4637 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4638 driver->architecture,
4639 driver->version,
4640 driver->config_file,
4641 r->config_file);
4643 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4644 driver->architecture,
4645 driver->version,
4646 driver->help_file,
4647 r->help_file);
4649 result = string_array_from_driver_info(mem_ctx,
4650 driver->dependent_files,
4651 &r->dependent_files,
4652 cservername,
4653 driver->architecture,
4654 driver->version);
4655 if (!W_ERROR_IS_OK(result)) {
4656 return result;
4659 FILL_DRIVER_STRING(mem_ctx,
4660 driver->monitor_name,
4661 r->monitor_name);
4663 FILL_DRIVER_STRING(mem_ctx,
4664 driver->default_datatype,
4665 r->default_datatype);
4668 result = string_array_from_driver_info(mem_ctx,
4669 driver->previous_names,
4670 &r->previous_names,
4671 NULL, NULL, 0);
4673 return result;
4676 /********************************************************************
4677 * fill a spoolss_DriverInfo5 struct
4678 ********************************************************************/
4680 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
4681 struct spoolss_DriverInfo5 *r,
4682 const struct spoolss_DriverInfo8 *driver,
4683 const char *servername)
4685 const char *cservername = canon_servername(servername);
4687 r->version = driver->version;
4689 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4690 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4691 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4692 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4694 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4695 driver->architecture,
4696 driver->version,
4697 driver->driver_path,
4698 r->driver_path);
4700 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4701 driver->architecture,
4702 driver->version,
4703 driver->data_file,
4704 r->data_file);
4706 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4707 driver->architecture,
4708 driver->version,
4709 driver->config_file,
4710 r->config_file);
4712 r->driver_attributes = 0;
4713 r->config_version = 0;
4714 r->driver_version = 0;
4716 return WERR_OK;
4718 /********************************************************************
4719 * fill a spoolss_DriverInfo6 struct
4720 ********************************************************************/
4722 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
4723 struct spoolss_DriverInfo6 *r,
4724 const struct spoolss_DriverInfo8 *driver,
4725 const char *servername)
4727 const char *cservername = canon_servername(servername);
4728 WERROR result;
4730 r->version = driver->version;
4732 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4733 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4734 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4735 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4737 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4738 driver->architecture,
4739 driver->version,
4740 driver->driver_path,
4741 r->driver_path);
4743 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4744 driver->architecture,
4745 driver->version,
4746 driver->data_file,
4747 r->data_file);
4749 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4750 driver->architecture,
4751 driver->version,
4752 driver->config_file,
4753 r->config_file);
4755 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4756 driver->architecture,
4757 driver->version,
4758 driver->help_file,
4759 r->help_file);
4761 FILL_DRIVER_STRING(mem_ctx,
4762 driver->monitor_name,
4763 r->monitor_name);
4765 FILL_DRIVER_STRING(mem_ctx,
4766 driver->default_datatype,
4767 r->default_datatype);
4769 result = string_array_from_driver_info(mem_ctx,
4770 driver->dependent_files,
4771 &r->dependent_files,
4772 cservername,
4773 driver->architecture,
4774 driver->version);
4775 if (!W_ERROR_IS_OK(result)) {
4776 return result;
4779 result = string_array_from_driver_info(mem_ctx,
4780 driver->previous_names,
4781 &r->previous_names,
4782 NULL, NULL, 0);
4783 if (!W_ERROR_IS_OK(result)) {
4784 return result;
4787 r->driver_date = driver->driver_date;
4788 r->driver_version = driver->driver_version;
4790 FILL_DRIVER_STRING(mem_ctx,
4791 driver->manufacturer_name,
4792 r->manufacturer_name);
4793 FILL_DRIVER_STRING(mem_ctx,
4794 driver->manufacturer_url,
4795 r->manufacturer_url);
4796 FILL_DRIVER_STRING(mem_ctx,
4797 driver->hardware_id,
4798 r->hardware_id);
4799 FILL_DRIVER_STRING(mem_ctx,
4800 driver->provider,
4801 r->provider);
4803 return WERR_OK;
4806 /********************************************************************
4807 * fill a spoolss_DriverInfo8 struct
4808 ********************************************************************/
4810 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
4811 struct spoolss_DriverInfo8 *r,
4812 const struct spoolss_DriverInfo8 *driver,
4813 const char *servername)
4815 const char *cservername = canon_servername(servername);
4816 WERROR result;
4818 r->version = driver->version;
4820 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4821 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4822 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4823 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4825 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4826 driver->architecture,
4827 driver->version,
4828 driver->driver_path,
4829 r->driver_path);
4831 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4832 driver->architecture,
4833 driver->version,
4834 driver->data_file,
4835 r->data_file);
4837 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4838 driver->architecture,
4839 driver->version,
4840 driver->config_file,
4841 r->config_file);
4843 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4844 driver->architecture,
4845 driver->version,
4846 driver->help_file,
4847 r->help_file);
4849 FILL_DRIVER_STRING(mem_ctx,
4850 driver->monitor_name,
4851 r->monitor_name);
4853 FILL_DRIVER_STRING(mem_ctx,
4854 driver->default_datatype,
4855 r->default_datatype);
4857 result = string_array_from_driver_info(mem_ctx,
4858 driver->dependent_files,
4859 &r->dependent_files,
4860 cservername,
4861 driver->architecture,
4862 driver->version);
4863 if (!W_ERROR_IS_OK(result)) {
4864 return result;
4867 result = string_array_from_driver_info(mem_ctx,
4868 driver->previous_names,
4869 &r->previous_names,
4870 NULL, NULL, 0);
4871 if (!W_ERROR_IS_OK(result)) {
4872 return result;
4875 r->driver_date = driver->driver_date;
4876 r->driver_version = driver->driver_version;
4878 FILL_DRIVER_STRING(mem_ctx,
4879 driver->manufacturer_name,
4880 r->manufacturer_name);
4881 FILL_DRIVER_STRING(mem_ctx,
4882 driver->manufacturer_url,
4883 r->manufacturer_url);
4884 FILL_DRIVER_STRING(mem_ctx,
4885 driver->hardware_id,
4886 r->hardware_id);
4887 FILL_DRIVER_STRING(mem_ctx,
4888 driver->provider,
4889 r->provider);
4891 FILL_DRIVER_STRING(mem_ctx,
4892 driver->print_processor,
4893 r->print_processor);
4894 FILL_DRIVER_STRING(mem_ctx,
4895 driver->vendor_setup,
4896 r->vendor_setup);
4898 result = string_array_from_driver_info(mem_ctx,
4899 driver->color_profiles,
4900 &r->color_profiles,
4901 NULL, NULL, 0);
4902 if (!W_ERROR_IS_OK(result)) {
4903 return result;
4906 FILL_DRIVER_STRING(mem_ctx,
4907 driver->inf_path,
4908 r->inf_path);
4910 r->printer_driver_attributes = driver->printer_driver_attributes;
4912 result = string_array_from_driver_info(mem_ctx,
4913 driver->core_driver_dependencies,
4914 &r->core_driver_dependencies,
4915 NULL, NULL, 0);
4916 if (!W_ERROR_IS_OK(result)) {
4917 return result;
4920 r->min_inbox_driver_ver_date = driver->min_inbox_driver_ver_date;
4921 r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
4923 return WERR_OK;
4926 #if 0 /* disabled until marshalling issues are resolved - gd */
4927 /********************************************************************
4928 ********************************************************************/
4930 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
4931 struct spoolss_DriverFileInfo *r,
4932 const char *cservername,
4933 const char *file_name,
4934 enum spoolss_DriverFileType file_type,
4935 uint32_t file_version)
4937 r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
4938 cservername, file_name);
4939 W_ERROR_HAVE_NO_MEMORY(r->file_name);
4940 r->file_type = file_type;
4941 r->file_version = file_version;
4943 return WERR_OK;
4946 /********************************************************************
4947 ********************************************************************/
4949 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
4950 const struct spoolss_DriverInfo8 *driver,
4951 const char *cservername,
4952 struct spoolss_DriverFileInfo **info_p,
4953 uint32_t *count_p)
4955 struct spoolss_DriverFileInfo *info = NULL;
4956 uint32_t count = 0;
4957 WERROR result;
4958 uint32_t i;
4960 *info_p = NULL;
4961 *count_p = 0;
4963 if (strlen(driver->driver_path)) {
4964 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4965 struct spoolss_DriverFileInfo,
4966 count + 1);
4967 W_ERROR_HAVE_NO_MEMORY(info);
4968 result = fill_spoolss_DriverFileInfo(info,
4969 &info[count],
4970 cservername,
4971 driver->driver_path,
4972 SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
4974 W_ERROR_NOT_OK_RETURN(result);
4975 count++;
4978 if (strlen(driver->config_file)) {
4979 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4980 struct spoolss_DriverFileInfo,
4981 count + 1);
4982 W_ERROR_HAVE_NO_MEMORY(info);
4983 result = fill_spoolss_DriverFileInfo(info,
4984 &info[count],
4985 cservername,
4986 driver->config_file,
4987 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
4989 W_ERROR_NOT_OK_RETURN(result);
4990 count++;
4993 if (strlen(driver->data_file)) {
4994 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4995 struct spoolss_DriverFileInfo,
4996 count + 1);
4997 W_ERROR_HAVE_NO_MEMORY(info);
4998 result = fill_spoolss_DriverFileInfo(info,
4999 &info[count],
5000 cservername,
5001 driver->data_file,
5002 SPOOLSS_DRIVER_FILE_TYPE_DATA,
5004 W_ERROR_NOT_OK_RETURN(result);
5005 count++;
5008 if (strlen(driver->help_file)) {
5009 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5010 struct spoolss_DriverFileInfo,
5011 count + 1);
5012 W_ERROR_HAVE_NO_MEMORY(info);
5013 result = fill_spoolss_DriverFileInfo(info,
5014 &info[count],
5015 cservername,
5016 driver->help_file,
5017 SPOOLSS_DRIVER_FILE_TYPE_HELP,
5019 W_ERROR_NOT_OK_RETURN(result);
5020 count++;
5023 for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5024 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5025 struct spoolss_DriverFileInfo,
5026 count + 1);
5027 W_ERROR_HAVE_NO_MEMORY(info);
5028 result = fill_spoolss_DriverFileInfo(info,
5029 &info[count],
5030 cservername,
5031 driver->dependent_files[i],
5032 SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5034 W_ERROR_NOT_OK_RETURN(result);
5035 count++;
5038 *info_p = info;
5039 *count_p = count;
5041 return WERR_OK;
5044 /********************************************************************
5045 * fill a spoolss_DriverInfo101 struct
5046 ********************************************************************/
5048 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5049 struct spoolss_DriverInfo101 *r,
5050 const struct spoolss_DriverInfo8 *driver,
5051 const char *servername)
5053 const char *cservername = canon_servername(servername);
5054 WERROR result;
5056 r->version = driver->version;
5058 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5059 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5060 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5061 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5063 result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5064 cservername,
5065 &r->file_info,
5066 &r->file_count);
5067 if (!W_ERROR_IS_OK(result)) {
5068 return result;
5071 FILL_DRIVER_STRING(mem_ctx,
5072 driver->monitor_name,
5073 r->monitor_name);
5075 FILL_DRIVER_STRING(mem_ctx,
5076 driver->default_datatype,
5077 r->default_datatype);
5079 result = string_array_from_driver_info(mem_ctx,
5080 driver->previous_names,
5081 &r->previous_names,
5082 NULL, NULL, 0);
5083 if (!W_ERROR_IS_OK(result)) {
5084 return result;
5087 r->driver_date = driver->driver_date;
5088 r->driver_version = driver->driver_version;
5090 FILL_DRIVER_STRING(mem_ctx,
5091 driver->manufacturer_name,
5092 r->manufacturer_name);
5093 FILL_DRIVER_STRING(mem_ctx,
5094 driver->manufacturer_url,
5095 r->manufacturer_url);
5096 FILL_DRIVER_STRING(mem_ctx,
5097 driver->hardware_id,
5098 r->hardware_id);
5099 FILL_DRIVER_STRING(mem_ctx,
5100 driver->provider,
5101 r->provider);
5103 return WERR_OK;
5105 #endif
5106 /********************************************************************
5107 ********************************************************************/
5109 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5110 struct auth_serversupplied_info *server_info,
5111 struct messaging_context *msg_ctx,
5112 uint32_t level,
5113 union spoolss_DriverInfo *r,
5114 int snum,
5115 const char *servername,
5116 const char *architecture,
5117 uint32_t version)
5119 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5120 struct spoolss_DriverInfo8 *driver;
5121 WERROR result;
5123 result = winreg_get_printer(mem_ctx,
5124 server_info,
5125 msg_ctx,
5126 servername,
5127 lp_const_servicename(snum),
5128 &pinfo2);
5130 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5131 win_errstr(result)));
5133 if (!W_ERROR_IS_OK(result)) {
5134 return WERR_INVALID_PRINTER_NAME;
5137 result = winreg_get_driver(mem_ctx, server_info, msg_ctx,
5138 architecture,
5139 pinfo2->drivername, version, &driver);
5141 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5142 win_errstr(result)));
5144 if (!W_ERROR_IS_OK(result)) {
5146 * Is this a W2k client ?
5149 if (version < 3) {
5150 talloc_free(pinfo2);
5151 return WERR_UNKNOWN_PRINTER_DRIVER;
5154 /* Yes - try again with a WinNT driver. */
5155 version = 2;
5156 result = winreg_get_driver(mem_ctx, server_info, msg_ctx,
5157 architecture,
5158 pinfo2->drivername,
5159 version, &driver);
5160 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5161 win_errstr(result)));
5162 if (!W_ERROR_IS_OK(result)) {
5163 talloc_free(pinfo2);
5164 return WERR_UNKNOWN_PRINTER_DRIVER;
5168 switch (level) {
5169 case 1:
5170 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5171 break;
5172 case 2:
5173 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5174 break;
5175 case 3:
5176 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5177 break;
5178 case 4:
5179 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5180 break;
5181 case 5:
5182 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5183 break;
5184 case 6:
5185 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5186 break;
5187 case 8:
5188 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5189 break;
5190 #if 0 /* disabled until marshalling issues are resolved - gd */
5191 case 101:
5192 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5193 break;
5194 #endif
5195 default:
5196 result = WERR_UNKNOWN_LEVEL;
5197 break;
5200 talloc_free(pinfo2);
5201 talloc_free(driver);
5203 return result;
5206 /****************************************************************
5207 _spoolss_GetPrinterDriver2
5208 ****************************************************************/
5210 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5211 struct spoolss_GetPrinterDriver2 *r)
5213 Printer_entry *printer;
5214 WERROR result;
5216 int snum;
5218 /* that's an [in out] buffer */
5220 if (!r->in.buffer && (r->in.offered != 0)) {
5221 return WERR_INVALID_PARAM;
5224 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5226 if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5227 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5228 return WERR_INVALID_PRINTER_NAME;
5231 *r->out.needed = 0;
5232 *r->out.server_major_version = 0;
5233 *r->out.server_minor_version = 0;
5235 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5236 return WERR_BADFID;
5239 result = construct_printer_driver_info_level(p->mem_ctx,
5240 p->server_info,
5241 p->msg_ctx,
5242 r->in.level, r->out.info,
5243 snum, printer->servername,
5244 r->in.architecture,
5245 r->in.client_major_version);
5246 if (!W_ERROR_IS_OK(result)) {
5247 TALLOC_FREE(r->out.info);
5248 return result;
5251 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5252 r->out.info, r->in.level);
5253 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5255 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5259 /****************************************************************
5260 _spoolss_StartPagePrinter
5261 ****************************************************************/
5263 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5264 struct spoolss_StartPagePrinter *r)
5266 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5268 if (!Printer) {
5269 DEBUG(3,("_spoolss_StartPagePrinter: "
5270 "Error in startpageprinter printer handle\n"));
5271 return WERR_BADFID;
5274 Printer->page_started = true;
5275 return WERR_OK;
5278 /****************************************************************
5279 _spoolss_EndPagePrinter
5280 ****************************************************************/
5282 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5283 struct spoolss_EndPagePrinter *r)
5285 int snum;
5287 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5289 if (!Printer) {
5290 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5291 OUR_HANDLE(r->in.handle)));
5292 return WERR_BADFID;
5295 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5296 return WERR_BADFID;
5298 Printer->page_started = false;
5299 print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5301 return WERR_OK;
5304 /****************************************************************
5305 _spoolss_StartDocPrinter
5306 ****************************************************************/
5308 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5309 struct spoolss_StartDocPrinter *r)
5311 struct spoolss_DocumentInfo1 *info_1;
5312 int snum;
5313 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5314 WERROR werr;
5316 if (!Printer) {
5317 DEBUG(2,("_spoolss_StartDocPrinter: "
5318 "Invalid handle (%s:%u:%u)\n",
5319 OUR_HANDLE(r->in.handle)));
5320 return WERR_BADFID;
5323 if (Printer->jobid) {
5324 DEBUG(2, ("_spoolss_StartDocPrinter: "
5325 "StartDocPrinter called twice! "
5326 "(existing jobid = %d)\n", Printer->jobid));
5327 return WERR_INVALID_HANDLE;
5330 if (r->in.level != 1) {
5331 return WERR_UNKNOWN_LEVEL;
5334 info_1 = r->in.info.info1;
5337 * a nice thing with NT is it doesn't listen to what you tell it.
5338 * when asked to send _only_ RAW datas, it tries to send datas
5339 * in EMF format.
5341 * So I add checks like in NT Server ...
5344 if (info_1->datatype) {
5345 if (strcmp(info_1->datatype, "RAW") != 0) {
5346 *r->out.job_id = 0;
5347 return WERR_INVALID_DATATYPE;
5351 /* get the share number of the printer */
5352 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5353 return WERR_BADFID;
5356 werr = print_job_start(p->server_info, p->msg_ctx,
5357 p->client_id->name, snum,
5358 info_1->document_name, info_1->output_file,
5359 Printer->devmode, &Printer->jobid);
5361 /* An error occured in print_job_start() so return an appropriate
5362 NT error code. */
5364 if (!W_ERROR_IS_OK(werr)) {
5365 return werr;
5368 Printer->document_started = true;
5369 *r->out.job_id = Printer->jobid;
5371 return WERR_OK;
5374 /****************************************************************
5375 _spoolss_EndDocPrinter
5376 ****************************************************************/
5378 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5379 struct spoolss_EndDocPrinter *r)
5381 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5382 NTSTATUS status;
5383 int snum;
5385 if (!Printer) {
5386 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5387 OUR_HANDLE(r->in.handle)));
5388 return WERR_BADFID;
5391 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5392 return WERR_BADFID;
5395 Printer->document_started = false;
5396 status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5397 if (!NT_STATUS_IS_OK(status)) {
5398 DEBUG(2, ("_spoolss_EndDocPrinter: "
5399 "print_job_end failed [%s]\n",
5400 nt_errstr(status)));
5403 Printer->jobid = 0;
5404 return ntstatus_to_werror(status);
5407 /****************************************************************
5408 _spoolss_WritePrinter
5409 ****************************************************************/
5411 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5412 struct spoolss_WritePrinter *r)
5414 ssize_t buffer_written;
5415 int snum;
5416 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5418 if (!Printer) {
5419 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5420 OUR_HANDLE(r->in.handle)));
5421 *r->out.num_written = r->in._data_size;
5422 return WERR_BADFID;
5425 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5426 return WERR_BADFID;
5428 /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5429 buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5430 snum, Printer->jobid,
5431 (const char *)r->in.data.data,
5432 (size_t)r->in._data_size);
5433 if (buffer_written == (ssize_t)-1) {
5434 *r->out.num_written = 0;
5435 if (errno == ENOSPC)
5436 return WERR_NO_SPOOL_SPACE;
5437 else
5438 return WERR_ACCESS_DENIED;
5441 *r->out.num_written = r->in._data_size;
5443 return WERR_OK;
5446 /********************************************************************
5447 * api_spoolss_getprinter
5448 * called from the spoolss dispatcher
5450 ********************************************************************/
5452 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5453 struct pipes_struct *p)
5455 int snum;
5456 WERROR errcode = WERR_BADFUNC;
5457 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5459 if (!Printer) {
5460 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5461 OUR_HANDLE(handle)));
5462 return WERR_BADFID;
5465 if (!get_printer_snum(p, handle, &snum, NULL))
5466 return WERR_BADFID;
5468 switch (command) {
5469 case SPOOLSS_PRINTER_CONTROL_PAUSE:
5470 errcode = print_queue_pause(p->server_info, p->msg_ctx, snum);
5471 break;
5472 case SPOOLSS_PRINTER_CONTROL_RESUME:
5473 case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5474 errcode = print_queue_resume(p->server_info, p->msg_ctx, snum);
5475 break;
5476 case SPOOLSS_PRINTER_CONTROL_PURGE:
5477 errcode = print_queue_purge(p->server_info, p->msg_ctx, snum);
5478 break;
5479 default:
5480 return WERR_UNKNOWN_LEVEL;
5483 return errcode;
5487 /****************************************************************
5488 _spoolss_AbortPrinter
5489 * From MSDN: "Deletes printer's spool file if printer is configured
5490 * for spooling"
5491 ****************************************************************/
5493 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
5494 struct spoolss_AbortPrinter *r)
5496 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
5497 int snum;
5498 WERROR errcode = WERR_OK;
5500 if (!Printer) {
5501 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5502 OUR_HANDLE(r->in.handle)));
5503 return WERR_BADFID;
5506 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5507 return WERR_BADFID;
5509 if (!Printer->document_started) {
5510 return WERR_SPL_NO_STARTDOC;
5513 errcode = print_job_delete(p->server_info, p->msg_ctx, snum,
5514 Printer->jobid);
5516 return errcode;
5519 /********************************************************************
5520 * called by spoolss_api_setprinter
5521 * when updating a printer description
5522 ********************************************************************/
5524 static WERROR update_printer_sec(struct policy_handle *handle,
5525 struct pipes_struct *p,
5526 struct sec_desc_buf *secdesc_ctr)
5528 struct spoolss_security_descriptor *new_secdesc = NULL;
5529 struct spoolss_security_descriptor *old_secdesc = NULL;
5530 const char *printer;
5531 WERROR result;
5532 int snum;
5534 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5536 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5537 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5538 OUR_HANDLE(handle)));
5540 result = WERR_BADFID;
5541 goto done;
5544 if (secdesc_ctr == NULL) {
5545 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5546 result = WERR_INVALID_PARAM;
5547 goto done;
5549 printer = lp_const_servicename(snum);
5551 /* Check the user has permissions to change the security
5552 descriptor. By experimentation with two NT machines, the user
5553 requires Full Access to the printer to change security
5554 information. */
5556 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5557 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5558 result = WERR_ACCESS_DENIED;
5559 goto done;
5562 /* NT seems to like setting the security descriptor even though
5563 nothing may have actually changed. */
5564 result = winreg_get_printer_secdesc(p->mem_ctx,
5565 p->server_info,
5566 p->msg_ctx,
5567 printer,
5568 &old_secdesc);
5569 if (!W_ERROR_IS_OK(result)) {
5570 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc() failed\n"));
5571 result = WERR_BADFID;
5572 goto done;
5575 if (DEBUGLEVEL >= 10) {
5576 struct security_acl *the_acl;
5577 int i;
5579 the_acl = old_secdesc->dacl;
5580 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5581 printer, the_acl->num_aces));
5583 for (i = 0; i < the_acl->num_aces; i++) {
5584 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5585 &the_acl->aces[i].trustee),
5586 the_acl->aces[i].access_mask));
5589 the_acl = secdesc_ctr->sd->dacl;
5591 if (the_acl) {
5592 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5593 printer, the_acl->num_aces));
5595 for (i = 0; i < the_acl->num_aces; i++) {
5596 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5597 &the_acl->aces[i].trustee),
5598 the_acl->aces[i].access_mask));
5600 } else {
5601 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5605 new_secdesc = sec_desc_merge(p->mem_ctx, secdesc_ctr->sd, old_secdesc);
5606 if (new_secdesc == NULL) {
5607 result = WERR_NOMEM;
5608 goto done;
5611 if (security_descriptor_equal(new_secdesc, old_secdesc)) {
5612 result = WERR_OK;
5613 goto done;
5616 result = winreg_set_printer_secdesc(p->mem_ctx,
5617 p->server_info,
5618 p->msg_ctx,
5619 printer,
5620 new_secdesc);
5622 done:
5623 return result;
5626 /********************************************************************
5627 Canonicalize printer info from a client
5628 ********************************************************************/
5630 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
5631 struct spoolss_SetPrinterInfo2 *info2,
5632 int snum)
5634 fstring printername;
5635 const char *p;
5637 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5638 "portname=%s drivername=%s comment=%s location=%s\n",
5639 info2->servername, info2->printername, info2->sharename,
5640 info2->portname, info2->drivername, info2->comment,
5641 info2->location));
5643 /* we force some elements to "correct" values */
5644 info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
5645 if (info2->servername == NULL) {
5646 return false;
5648 info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
5649 if (info2->sharename == NULL) {
5650 return false;
5653 /* check to see if we allow printername != sharename */
5654 if (lp_force_printername(snum)) {
5655 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
5656 global_myname(), info2->sharename);
5657 } else {
5658 /* make sure printername is in \\server\printername format */
5659 fstrcpy(printername, info2->printername);
5660 p = printername;
5661 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5662 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5663 p++;
5666 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
5667 global_myname(), p);
5669 if (info2->printername == NULL) {
5670 return false;
5673 info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5674 info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5676 return true;
5679 /****************************************************************************
5680 ****************************************************************************/
5682 static WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri)
5684 char *cmd = lp_addport_cmd();
5685 char *command = NULL;
5686 int ret;
5687 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5688 bool is_print_op = false;
5690 if ( !*cmd ) {
5691 return WERR_ACCESS_DENIED;
5694 command = talloc_asprintf(ctx,
5695 "%s \"%s\" \"%s\"", cmd, portname, uri );
5696 if (!command) {
5697 return WERR_NOMEM;
5700 if ( token )
5701 is_print_op = user_has_privileges( token, &se_printop );
5703 DEBUG(10,("Running [%s]\n", command));
5705 /********* BEGIN SePrintOperatorPrivilege **********/
5707 if ( is_print_op )
5708 become_root();
5710 ret = smbrun(command, NULL);
5712 if ( is_print_op )
5713 unbecome_root();
5715 /********* END SePrintOperatorPrivilege **********/
5717 DEBUGADD(10,("returned [%d]\n", ret));
5719 TALLOC_FREE(command);
5721 if ( ret != 0 ) {
5722 return WERR_ACCESS_DENIED;
5725 return WERR_OK;
5728 /****************************************************************************
5729 ****************************************************************************/
5731 static bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token,
5732 struct spoolss_SetPrinterInfo2 *info2,
5733 const char *remote_machine,
5734 struct messaging_context *msg_ctx)
5736 char *cmd = lp_addprinter_cmd();
5737 char **qlines;
5738 char *command = NULL;
5739 int numlines;
5740 int ret;
5741 int fd;
5742 SE_PRIV se_printop = SE_PRINT_OPERATOR;
5743 bool is_print_op = false;
5745 if (!remote_machine) {
5746 return false;
5749 command = talloc_asprintf(ctx,
5750 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5751 cmd, info2->printername, info2->sharename,
5752 info2->portname, info2->drivername,
5753 info2->location, info2->comment, remote_machine);
5754 if (!command) {
5755 return false;
5758 if ( token )
5759 is_print_op = user_has_privileges( token, &se_printop );
5761 DEBUG(10,("Running [%s]\n", command));
5763 /********* BEGIN SePrintOperatorPrivilege **********/
5765 if ( is_print_op )
5766 become_root();
5768 if ( (ret = smbrun(command, &fd)) == 0 ) {
5769 /* Tell everyone we updated smb.conf. */
5770 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
5773 if ( is_print_op )
5774 unbecome_root();
5776 /********* END SePrintOperatorPrivilege **********/
5778 DEBUGADD(10,("returned [%d]\n", ret));
5780 TALLOC_FREE(command);
5782 if ( ret != 0 ) {
5783 if (fd != -1)
5784 close(fd);
5785 return false;
5788 /* reload our services immediately */
5789 become_root();
5790 reload_services(msg_ctx, -1, false);
5791 unbecome_root();
5793 numlines = 0;
5794 /* Get lines and convert them back to dos-codepage */
5795 qlines = fd_lines_load(fd, &numlines, 0, NULL);
5796 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5797 close(fd);
5799 /* Set the portname to what the script says the portname should be. */
5800 /* but don't require anything to be return from the script exit a good error code */
5802 if (numlines) {
5803 /* Set the portname to what the script says the portname should be. */
5804 info2->portname = talloc_strdup(ctx, qlines[0]);
5805 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5808 TALLOC_FREE(qlines);
5809 return true;
5812 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
5813 struct auth_serversupplied_info *server_info,
5814 struct messaging_context *msg_ctx,
5815 int snum,
5816 struct spoolss_SetPrinterInfo2 *printer,
5817 struct spoolss_PrinterInfo2 *old_printer)
5819 bool force_update = (old_printer == NULL);
5820 const char *dnsdomname;
5821 const char *longname;
5822 const char *uncname;
5823 const char *spooling;
5824 DATA_BLOB buffer;
5825 WERROR result = WERR_OK;
5827 if (force_update || !strequal(printer->drivername, old_printer->drivername)) {
5828 push_reg_sz(mem_ctx, &buffer, printer->drivername);
5829 winreg_set_printer_dataex(mem_ctx,
5830 server_info,
5831 msg_ctx,
5832 printer->sharename,
5833 SPOOL_DSSPOOLER_KEY,
5834 SPOOL_REG_DRIVERNAME,
5835 REG_SZ,
5836 buffer.data,
5837 buffer.length);
5839 if (!force_update) {
5840 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
5841 printer->drivername));
5843 notify_printer_driver(server_event_context(), msg_ctx,
5844 snum, printer->drivername);
5848 if (force_update || !strequal(printer->comment, old_printer->comment)) {
5849 push_reg_sz(mem_ctx, &buffer, printer->comment);
5850 winreg_set_printer_dataex(mem_ctx,
5851 server_info,
5852 msg_ctx,
5853 printer->sharename,
5854 SPOOL_DSSPOOLER_KEY,
5855 SPOOL_REG_DESCRIPTION,
5856 REG_SZ,
5857 buffer.data,
5858 buffer.length);
5860 if (!force_update) {
5861 notify_printer_comment(server_event_context(), msg_ctx,
5862 snum, printer->comment);
5866 if (force_update || !strequal(printer->sharename, old_printer->sharename)) {
5867 push_reg_sz(mem_ctx, &buffer, printer->sharename);
5868 winreg_set_printer_dataex(mem_ctx,
5869 server_info,
5870 msg_ctx,
5871 printer->sharename,
5872 SPOOL_DSSPOOLER_KEY,
5873 SPOOL_REG_PRINTSHARENAME,
5874 REG_SZ,
5875 buffer.data,
5876 buffer.length);
5878 if (!force_update) {
5879 notify_printer_sharename(server_event_context(),
5880 msg_ctx,
5881 snum, printer->sharename);
5885 if (force_update || !strequal(printer->printername, old_printer->printername)) {
5886 const char *p;
5888 p = strrchr(printer->printername, '\\' );
5889 if (p != NULL) {
5890 p++;
5891 } else {
5892 p = printer->printername;
5895 push_reg_sz(mem_ctx, &buffer, p);
5896 winreg_set_printer_dataex(mem_ctx,
5897 server_info,
5898 msg_ctx,
5899 printer->sharename,
5900 SPOOL_DSSPOOLER_KEY,
5901 SPOOL_REG_PRINTERNAME,
5902 REG_SZ,
5903 buffer.data,
5904 buffer.length);
5906 if (!force_update) {
5907 notify_printer_printername(server_event_context(),
5908 msg_ctx, snum, p);
5912 if (force_update || !strequal(printer->portname, old_printer->portname)) {
5913 push_reg_sz(mem_ctx, &buffer, printer->portname);
5914 winreg_set_printer_dataex(mem_ctx,
5915 server_info,
5916 msg_ctx,
5917 printer->sharename,
5918 SPOOL_DSSPOOLER_KEY,
5919 SPOOL_REG_PORTNAME,
5920 REG_SZ,
5921 buffer.data,
5922 buffer.length);
5924 if (!force_update) {
5925 notify_printer_port(server_event_context(),
5926 msg_ctx, snum, printer->portname);
5930 if (force_update || !strequal(printer->location, old_printer->location)) {
5931 push_reg_sz(mem_ctx, &buffer, printer->location);
5932 winreg_set_printer_dataex(mem_ctx,
5933 server_info,
5934 msg_ctx,
5935 printer->sharename,
5936 SPOOL_DSSPOOLER_KEY,
5937 SPOOL_REG_LOCATION,
5938 REG_SZ,
5939 buffer.data,
5940 buffer.length);
5942 if (!force_update) {
5943 notify_printer_location(server_event_context(),
5944 msg_ctx, snum,
5945 printer->location);
5949 if (force_update || !strequal(printer->sepfile, old_printer->sepfile)) {
5950 push_reg_sz(mem_ctx, &buffer, printer->sepfile);
5951 winreg_set_printer_dataex(mem_ctx,
5952 server_info,
5953 msg_ctx,
5954 printer->sharename,
5955 SPOOL_DSSPOOLER_KEY,
5956 SPOOL_REG_PRINTSEPARATORFILE,
5957 REG_SZ,
5958 buffer.data,
5959 buffer.length);
5961 if (!force_update) {
5962 notify_printer_location(server_event_context(),
5963 msg_ctx, snum,
5964 printer->location);
5968 if (force_update || printer->starttime != old_printer->starttime) {
5969 buffer = data_blob_talloc(mem_ctx, NULL, 4);
5970 SIVAL(buffer.data, 0, printer->starttime);
5971 winreg_set_printer_dataex(mem_ctx,
5972 server_info,
5973 msg_ctx,
5974 printer->sharename,
5975 SPOOL_DSSPOOLER_KEY,
5976 SPOOL_REG_PRINTSTARTTIME,
5977 REG_DWORD,
5978 buffer.data,
5979 buffer.length);
5982 if (force_update || printer->untiltime != old_printer->untiltime) {
5983 buffer = data_blob_talloc(mem_ctx, NULL, 4);
5984 SIVAL(buffer.data, 0, printer->untiltime);
5985 winreg_set_printer_dataex(mem_ctx,
5986 server_info,
5987 msg_ctx,
5988 printer->sharename,
5989 SPOOL_DSSPOOLER_KEY,
5990 SPOOL_REG_PRINTENDTIME,
5991 REG_DWORD,
5992 buffer.data,
5993 buffer.length);
5996 if (force_update || printer->priority != old_printer->priority) {
5997 buffer = data_blob_talloc(mem_ctx, NULL, 4);
5998 SIVAL(buffer.data, 0, printer->priority);
5999 winreg_set_printer_dataex(mem_ctx,
6000 server_info,
6001 msg_ctx,
6002 printer->sharename,
6003 SPOOL_DSSPOOLER_KEY,
6004 SPOOL_REG_PRIORITY,
6005 REG_DWORD,
6006 buffer.data,
6007 buffer.length);
6010 if (force_update || printer->attributes != old_printer->attributes) {
6011 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6012 SIVAL(buffer.data, 0, (printer->attributes &
6013 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6014 winreg_set_printer_dataex(mem_ctx,
6015 server_info,
6016 msg_ctx,
6017 printer->sharename,
6018 SPOOL_DSSPOOLER_KEY,
6019 SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6020 REG_DWORD,
6021 buffer.data,
6022 buffer.length);
6024 switch (printer->attributes & 0x3) {
6025 case 0:
6026 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6027 break;
6028 case 1:
6029 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6030 break;
6031 case 2:
6032 spooling = SPOOL_REGVAL_PRINTDIRECT;
6033 break;
6034 default:
6035 spooling = "unknown";
6037 push_reg_sz(mem_ctx, &buffer, spooling);
6038 winreg_set_printer_dataex(mem_ctx,
6039 server_info,
6040 msg_ctx,
6041 printer->sharename,
6042 SPOOL_DSSPOOLER_KEY,
6043 SPOOL_REG_PRINTSPOOLING,
6044 REG_SZ,
6045 buffer.data,
6046 buffer.length);
6049 push_reg_sz(mem_ctx, &buffer, global_myname());
6050 winreg_set_printer_dataex(mem_ctx,
6051 server_info,
6052 msg_ctx,
6053 printer->sharename,
6054 SPOOL_DSSPOOLER_KEY,
6055 SPOOL_REG_SHORTSERVERNAME,
6056 REG_SZ,
6057 buffer.data,
6058 buffer.length);
6060 dnsdomname = get_mydnsfullname();
6061 if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6062 longname = talloc_strdup(mem_ctx, dnsdomname);
6063 } else {
6064 longname = talloc_strdup(mem_ctx, global_myname());
6066 if (longname == NULL) {
6067 result = WERR_NOMEM;
6068 goto done;
6071 push_reg_sz(mem_ctx, &buffer, longname);
6072 winreg_set_printer_dataex(mem_ctx,
6073 server_info,
6074 msg_ctx,
6075 printer->sharename,
6076 SPOOL_DSSPOOLER_KEY,
6077 SPOOL_REG_SERVERNAME,
6078 REG_SZ,
6079 buffer.data,
6080 buffer.length);
6082 uncname = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6083 global_myname(), printer->sharename);
6084 push_reg_sz(mem_ctx, &buffer, uncname);
6085 winreg_set_printer_dataex(mem_ctx,
6086 server_info,
6087 msg_ctx,
6088 printer->sharename,
6089 SPOOL_DSSPOOLER_KEY,
6090 SPOOL_REG_UNCNAME,
6091 REG_SZ,
6092 buffer.data,
6093 buffer.length);
6095 done:
6096 return result;
6099 /********************************************************************
6100 * Called by spoolss_api_setprinter
6101 * when updating a printer description.
6102 ********************************************************************/
6104 static WERROR update_printer(struct pipes_struct *p,
6105 struct policy_handle *handle,
6106 struct spoolss_SetPrinterInfoCtr *info_ctr,
6107 struct spoolss_DeviceMode *devmode)
6109 uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6110 struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6111 struct spoolss_PrinterInfo2 *old_printer;
6112 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6113 const char *servername = NULL;
6114 int snum;
6115 WERROR result = WERR_OK;
6116 TALLOC_CTX *tmp_ctx;
6118 DEBUG(8,("update_printer\n"));
6120 tmp_ctx = talloc_new(p->mem_ctx);
6121 if (tmp_ctx == NULL) {
6122 return WERR_NOMEM;
6125 if (!Printer) {
6126 result = WERR_BADFID;
6127 goto done;
6130 if (!get_printer_snum(p, handle, &snum, NULL)) {
6131 result = WERR_BADFID;
6132 goto done;
6135 if (Printer != NULL || Printer->servername != NULL) {
6136 servername = Printer->servername;
6139 result = winreg_get_printer(tmp_ctx,
6140 p->server_info,
6141 p->msg_ctx,
6142 servername,
6143 lp_const_servicename(snum),
6144 &old_printer);
6145 if (!W_ERROR_IS_OK(result)) {
6146 result = WERR_BADFID;
6147 goto done;
6150 /* Do sanity check on the requested changes for Samba */
6151 if (!check_printer_ok(tmp_ctx, printer, snum)) {
6152 result = WERR_INVALID_PARAM;
6153 goto done;
6156 /* FIXME!!! If the driver has changed we really should verify that
6157 it is installed before doing much else --jerry */
6159 /* Check calling user has permission to update printer description */
6160 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6161 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6162 result = WERR_ACCESS_DENIED;
6163 goto done;
6166 /* Call addprinter hook */
6167 /* Check changes to see if this is really needed */
6169 if (*lp_addprinter_cmd() &&
6170 (!strequal(printer->drivername, old_printer->drivername) ||
6171 !strequal(printer->comment, old_printer->comment) ||
6172 !strequal(printer->portname, old_printer->portname) ||
6173 !strequal(printer->location, old_printer->location)) )
6175 /* add_printer_hook() will call reload_services() */
6176 if (!add_printer_hook(tmp_ctx, p->server_info->ptok,
6177 printer, p->client_id->addr,
6178 p->msg_ctx)) {
6179 result = WERR_ACCESS_DENIED;
6180 goto done;
6184 update_dsspooler(tmp_ctx,
6185 p->server_info,
6186 p->msg_ctx,
6187 snum,
6188 printer,
6189 old_printer);
6191 printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6193 if (devmode == NULL) {
6194 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6196 result = winreg_update_printer(tmp_ctx,
6197 p->server_info,
6198 p->msg_ctx,
6199 printer->sharename,
6200 printer_mask,
6201 printer,
6202 devmode,
6203 NULL);
6205 done:
6206 talloc_free(tmp_ctx);
6208 return result;
6211 /****************************************************************************
6212 ****************************************************************************/
6213 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6214 struct policy_handle *handle,
6215 struct spoolss_SetPrinterInfo7 *info7)
6217 #ifdef HAVE_ADS
6218 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6219 WERROR result;
6220 int snum;
6221 Printer_entry *Printer;
6223 if ( lp_security() != SEC_ADS ) {
6224 return WERR_UNKNOWN_LEVEL;
6227 Printer = find_printer_index_by_hnd(p, handle);
6229 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6231 if (!Printer)
6232 return WERR_BADFID;
6234 if (!get_printer_snum(p, handle, &snum, NULL))
6235 return WERR_BADFID;
6237 result = winreg_get_printer(p->mem_ctx, p->server_info, p->msg_ctx,
6238 Printer->servername,
6239 lp_servicename(snum), &pinfo2);
6240 if (!W_ERROR_IS_OK(result)) {
6241 return WERR_BADFID;
6244 nt_printer_publish(pinfo2, p->server_info, p->msg_ctx, pinfo2,
6245 info7->action);
6247 TALLOC_FREE(pinfo2);
6248 return WERR_OK;
6249 #else
6250 return WERR_UNKNOWN_LEVEL;
6251 #endif
6254 /********************************************************************
6255 ********************************************************************/
6257 static WERROR update_printer_devmode(struct pipes_struct *p,
6258 struct policy_handle *handle,
6259 struct spoolss_DeviceMode *devmode)
6261 int snum;
6262 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6263 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6265 DEBUG(8,("update_printer_devmode\n"));
6267 if (!Printer) {
6268 return WERR_BADFID;
6271 if (!get_printer_snum(p, handle, &snum, NULL)) {
6272 return WERR_BADFID;
6275 /* Check calling user has permission to update printer description */
6276 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6277 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6278 return WERR_ACCESS_DENIED;
6281 return winreg_update_printer(p->mem_ctx,
6282 p->server_info,
6283 p->msg_ctx,
6284 lp_const_servicename(snum),
6285 info2_mask,
6286 NULL,
6287 devmode,
6288 NULL);
6292 /****************************************************************
6293 _spoolss_SetPrinter
6294 ****************************************************************/
6296 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6297 struct spoolss_SetPrinter *r)
6299 WERROR result;
6301 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
6303 if (!Printer) {
6304 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6305 OUR_HANDLE(r->in.handle)));
6306 return WERR_BADFID;
6309 /* check the level */
6310 switch (r->in.info_ctr->level) {
6311 case 0:
6312 return control_printer(r->in.handle, r->in.command, p);
6313 case 2:
6314 result = update_printer(p, r->in.handle,
6315 r->in.info_ctr,
6316 r->in.devmode_ctr->devmode);
6317 if (!W_ERROR_IS_OK(result))
6318 return result;
6319 if (r->in.secdesc_ctr->sd)
6320 result = update_printer_sec(r->in.handle, p,
6321 r->in.secdesc_ctr);
6322 return result;
6323 case 3:
6324 return update_printer_sec(r->in.handle, p,
6325 r->in.secdesc_ctr);
6326 case 7:
6327 return publish_or_unpublish_printer(p, r->in.handle,
6328 r->in.info_ctr->info.info7);
6329 case 8:
6330 return update_printer_devmode(p, r->in.handle,
6331 r->in.devmode_ctr->devmode);
6332 default:
6333 return WERR_UNKNOWN_LEVEL;
6337 /****************************************************************
6338 _spoolss_FindClosePrinterNotify
6339 ****************************************************************/
6341 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
6342 struct spoolss_FindClosePrinterNotify *r)
6344 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
6346 if (!Printer) {
6347 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6348 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6349 return WERR_BADFID;
6352 if (Printer->notify.client_connected == true) {
6353 int snum = -1;
6355 if ( Printer->printer_type == SPLHND_SERVER)
6356 snum = -1;
6357 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6358 !get_printer_snum(p, r->in.handle, &snum, NULL) )
6359 return WERR_BADFID;
6361 srv_spoolss_replycloseprinter(
6362 snum, &Printer->notify.client_hnd, p->msg_ctx);
6365 Printer->notify.flags=0;
6366 Printer->notify.options=0;
6367 Printer->notify.localmachine[0]='\0';
6368 Printer->notify.printerlocal=0;
6369 TALLOC_FREE(Printer->notify.option);
6370 Printer->notify.client_connected = false;
6372 return WERR_OK;
6375 /****************************************************************
6376 _spoolss_AddJob
6377 ****************************************************************/
6379 WERROR _spoolss_AddJob(struct pipes_struct *p,
6380 struct spoolss_AddJob *r)
6382 if (!r->in.buffer && (r->in.offered != 0)) {
6383 return WERR_INVALID_PARAM;
6386 /* this is what a NT server returns for AddJob. AddJob must fail on
6387 * non-local printers */
6389 if (r->in.level != 1) {
6390 return WERR_UNKNOWN_LEVEL;
6393 return WERR_INVALID_PARAM;
6396 /****************************************************************************
6397 fill_job_info1
6398 ****************************************************************************/
6400 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6401 struct spoolss_JobInfo1 *r,
6402 const print_queue_struct *queue,
6403 int position, int snum,
6404 struct spoolss_PrinterInfo2 *pinfo2)
6406 struct tm *t;
6408 t = gmtime(&queue->time);
6410 r->job_id = queue->job;
6412 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6413 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6414 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
6415 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6416 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6417 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6418 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6419 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6420 r->data_type = talloc_strdup(mem_ctx, "RAW");
6421 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6422 r->text_status = talloc_strdup(mem_ctx, "");
6423 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6425 r->status = nt_printj_status(queue->status);
6426 r->priority = queue->priority;
6427 r->position = position;
6428 r->total_pages = queue->page_count;
6429 r->pages_printed = 0; /* ??? */
6431 init_systemtime(&r->submitted, t);
6433 return WERR_OK;
6436 /****************************************************************************
6437 fill_job_info2
6438 ****************************************************************************/
6440 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6441 struct spoolss_JobInfo2 *r,
6442 const print_queue_struct *queue,
6443 int position, int snum,
6444 struct spoolss_PrinterInfo2 *pinfo2,
6445 struct spoolss_DeviceMode *devmode)
6447 struct tm *t;
6449 t = gmtime(&queue->time);
6451 r->job_id = queue->job;
6453 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6454 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6455 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
6456 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6457 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6458 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6459 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6460 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6461 r->notify_name = talloc_strdup(mem_ctx, queue->fs_user);
6462 W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6463 r->data_type = talloc_strdup(mem_ctx, "RAW");
6464 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6465 r->print_processor = talloc_strdup(mem_ctx, "winprint");
6466 W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6467 r->parameters = talloc_strdup(mem_ctx, "");
6468 W_ERROR_HAVE_NO_MEMORY(r->parameters);
6469 r->driver_name = talloc_strdup(mem_ctx, pinfo2->drivername);
6470 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6472 r->devmode = devmode;
6474 r->text_status = talloc_strdup(mem_ctx, "");
6475 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6477 r->secdesc = NULL;
6479 r->status = nt_printj_status(queue->status);
6480 r->priority = queue->priority;
6481 r->position = position;
6482 r->start_time = 0;
6483 r->until_time = 0;
6484 r->total_pages = queue->page_count;
6485 r->size = queue->size;
6486 init_systemtime(&r->submitted, t);
6487 r->time = 0;
6488 r->pages_printed = 0; /* ??? */
6490 return WERR_OK;
6493 /****************************************************************************
6494 fill_job_info3
6495 ****************************************************************************/
6497 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6498 struct spoolss_JobInfo3 *r,
6499 const print_queue_struct *queue,
6500 const print_queue_struct *next_queue,
6501 int position, int snum,
6502 struct spoolss_PrinterInfo2 *pinfo2)
6504 r->job_id = queue->job;
6505 r->next_job_id = 0;
6506 if (next_queue) {
6507 r->next_job_id = next_queue->job;
6509 r->reserved = 0;
6511 return WERR_OK;
6514 /****************************************************************************
6515 Enumjobs at level 1.
6516 ****************************************************************************/
6518 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6519 const print_queue_struct *queue,
6520 uint32_t num_queues, int snum,
6521 struct spoolss_PrinterInfo2 *pinfo2,
6522 union spoolss_JobInfo **info_p,
6523 uint32_t *count)
6525 union spoolss_JobInfo *info;
6526 int i;
6527 WERROR result = WERR_OK;
6529 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6530 W_ERROR_HAVE_NO_MEMORY(info);
6532 *count = num_queues;
6534 for (i=0; i<*count; i++) {
6535 result = fill_job_info1(info,
6536 &info[i].info1,
6537 &queue[i],
6539 snum,
6540 pinfo2);
6541 if (!W_ERROR_IS_OK(result)) {
6542 goto out;
6546 out:
6547 if (!W_ERROR_IS_OK(result)) {
6548 TALLOC_FREE(info);
6549 *count = 0;
6550 return result;
6553 *info_p = info;
6555 return WERR_OK;
6558 /****************************************************************************
6559 Enumjobs at level 2.
6560 ****************************************************************************/
6562 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6563 const print_queue_struct *queue,
6564 uint32_t num_queues, int snum,
6565 struct spoolss_PrinterInfo2 *pinfo2,
6566 union spoolss_JobInfo **info_p,
6567 uint32_t *count)
6569 union spoolss_JobInfo *info;
6570 int i;
6571 WERROR result = WERR_OK;
6573 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6574 W_ERROR_HAVE_NO_MEMORY(info);
6576 *count = num_queues;
6578 for (i=0; i<*count; i++) {
6579 struct spoolss_DeviceMode *devmode;
6581 result = spoolss_create_default_devmode(info,
6582 pinfo2->printername,
6583 &devmode);
6584 if (!W_ERROR_IS_OK(result)) {
6585 DEBUG(3, ("Can't proceed w/o a devmode!"));
6586 goto out;
6589 result = fill_job_info2(info,
6590 &info[i].info2,
6591 &queue[i],
6593 snum,
6594 pinfo2,
6595 devmode);
6596 if (!W_ERROR_IS_OK(result)) {
6597 goto out;
6601 out:
6602 if (!W_ERROR_IS_OK(result)) {
6603 TALLOC_FREE(info);
6604 *count = 0;
6605 return result;
6608 *info_p = info;
6610 return WERR_OK;
6613 /****************************************************************************
6614 Enumjobs at level 3.
6615 ****************************************************************************/
6617 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
6618 const print_queue_struct *queue,
6619 uint32_t num_queues, int snum,
6620 struct spoolss_PrinterInfo2 *pinfo2,
6621 union spoolss_JobInfo **info_p,
6622 uint32_t *count)
6624 union spoolss_JobInfo *info;
6625 int i;
6626 WERROR result = WERR_OK;
6628 info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6629 W_ERROR_HAVE_NO_MEMORY(info);
6631 *count = num_queues;
6633 for (i=0; i<*count; i++) {
6634 const print_queue_struct *next_queue = NULL;
6636 if (i+1 < *count) {
6637 next_queue = &queue[i+1];
6640 result = fill_job_info3(info,
6641 &info[i].info3,
6642 &queue[i],
6643 next_queue,
6645 snum,
6646 pinfo2);
6647 if (!W_ERROR_IS_OK(result)) {
6648 goto out;
6652 out:
6653 if (!W_ERROR_IS_OK(result)) {
6654 TALLOC_FREE(info);
6655 *count = 0;
6656 return result;
6659 *info_p = info;
6661 return WERR_OK;
6664 /****************************************************************
6665 _spoolss_EnumJobs
6666 ****************************************************************/
6668 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
6669 struct spoolss_EnumJobs *r)
6671 WERROR result;
6672 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6673 int snum;
6674 print_status_struct prt_status;
6675 print_queue_struct *queue = NULL;
6676 uint32_t count;
6678 /* that's an [in out] buffer */
6680 if (!r->in.buffer && (r->in.offered != 0)) {
6681 return WERR_INVALID_PARAM;
6684 DEBUG(4,("_spoolss_EnumJobs\n"));
6686 *r->out.needed = 0;
6687 *r->out.count = 0;
6688 *r->out.info = NULL;
6690 /* lookup the printer snum and tdb entry */
6692 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6693 return WERR_BADFID;
6696 result = winreg_get_printer(p->mem_ctx, p->server_info, p->msg_ctx,
6697 NULL, lp_servicename(snum), &pinfo2);
6698 if (!W_ERROR_IS_OK(result)) {
6699 return result;
6702 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
6703 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
6704 count, prt_status.status, prt_status.message));
6706 if (count == 0) {
6707 SAFE_FREE(queue);
6708 TALLOC_FREE(pinfo2);
6709 return WERR_OK;
6712 switch (r->in.level) {
6713 case 1:
6714 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
6715 pinfo2, r->out.info, r->out.count);
6716 break;
6717 case 2:
6718 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
6719 pinfo2, r->out.info, r->out.count);
6720 break;
6721 case 3:
6722 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
6723 pinfo2, r->out.info, r->out.count);
6724 break;
6725 default:
6726 result = WERR_UNKNOWN_LEVEL;
6727 break;
6730 SAFE_FREE(queue);
6731 TALLOC_FREE(pinfo2);
6733 if (!W_ERROR_IS_OK(result)) {
6734 return result;
6737 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6738 spoolss_EnumJobs,
6739 *r->out.info, r->in.level,
6740 *r->out.count);
6741 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6742 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6744 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6747 /****************************************************************
6748 _spoolss_ScheduleJob
6749 ****************************************************************/
6751 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
6752 struct spoolss_ScheduleJob *r)
6754 return WERR_OK;
6757 /****************************************************************
6758 ****************************************************************/
6760 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
6761 struct messaging_context *msg_ctx,
6762 const char *printer_name,
6763 uint32_t job_id,
6764 struct spoolss_SetJobInfo1 *r)
6766 char *old_doc_name;
6768 if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
6769 return WERR_BADFID;
6772 if (strequal(old_doc_name, r->document_name)) {
6773 return WERR_OK;
6776 if (!print_job_set_name(server_event_context(), msg_ctx,
6777 printer_name, job_id, r->document_name)) {
6778 return WERR_BADFID;
6781 return WERR_OK;
6784 /****************************************************************
6785 _spoolss_SetJob
6786 ****************************************************************/
6788 WERROR _spoolss_SetJob(struct pipes_struct *p,
6789 struct spoolss_SetJob *r)
6791 int snum;
6792 WERROR errcode = WERR_BADFUNC;
6794 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6795 return WERR_BADFID;
6798 if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
6799 return WERR_INVALID_PRINTER_NAME;
6802 switch (r->in.command) {
6803 case SPOOLSS_JOB_CONTROL_CANCEL:
6804 case SPOOLSS_JOB_CONTROL_DELETE:
6805 errcode = print_job_delete(p->server_info, p->msg_ctx,
6806 snum, r->in.job_id);
6807 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
6808 errcode = WERR_OK;
6810 break;
6811 case SPOOLSS_JOB_CONTROL_PAUSE:
6812 if (print_job_pause(p->server_info, p->msg_ctx,
6813 snum, r->in.job_id, &errcode)) {
6814 errcode = WERR_OK;
6816 break;
6817 case SPOOLSS_JOB_CONTROL_RESTART:
6818 case SPOOLSS_JOB_CONTROL_RESUME:
6819 if (print_job_resume(p->server_info, p->msg_ctx,
6820 snum, r->in.job_id, &errcode)) {
6821 errcode = WERR_OK;
6823 break;
6824 case 0:
6825 errcode = WERR_OK;
6826 break;
6827 default:
6828 return WERR_UNKNOWN_LEVEL;
6831 if (!W_ERROR_IS_OK(errcode)) {
6832 return errcode;
6835 if (r->in.ctr == NULL) {
6836 return errcode;
6839 switch (r->in.ctr->level) {
6840 case 1:
6841 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
6842 lp_const_servicename(snum),
6843 r->in.job_id,
6844 r->in.ctr->info.info1);
6845 break;
6846 case 2:
6847 case 3:
6848 case 4:
6849 default:
6850 return WERR_UNKNOWN_LEVEL;
6853 return errcode;
6856 /****************************************************************************
6857 Enumerates all printer drivers by level and architecture.
6858 ****************************************************************************/
6860 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
6861 struct auth_serversupplied_info *server_info,
6862 struct messaging_context *msg_ctx,
6863 const char *servername,
6864 const char *architecture,
6865 uint32_t level,
6866 union spoolss_DriverInfo **info_p,
6867 uint32_t *count_p)
6869 int i;
6870 uint32_t version;
6871 struct spoolss_DriverInfo8 *driver;
6872 union spoolss_DriverInfo *info = NULL;
6873 uint32_t count = 0;
6874 WERROR result = WERR_OK;
6875 uint32_t num_drivers;
6876 const char **drivers;
6878 *count_p = 0;
6879 *info_p = NULL;
6881 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6882 result = winreg_get_driver_list(mem_ctx, server_info, msg_ctx,
6883 architecture, version,
6884 &num_drivers, &drivers);
6885 if (!W_ERROR_IS_OK(result)) {
6886 goto out;
6888 DEBUG(4, ("we have:[%d] drivers in environment"
6889 " [%s] and version [%d]\n",
6890 num_drivers, architecture, version));
6892 if (num_drivers != 0) {
6893 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
6894 union spoolss_DriverInfo,
6895 count + num_drivers);
6896 if (!info) {
6897 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
6898 "failed to enlarge driver info buffer!\n"));
6899 result = WERR_NOMEM;
6900 goto out;
6904 for (i = 0; i < num_drivers; i++) {
6905 DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
6907 result = winreg_get_driver(mem_ctx, server_info,
6908 msg_ctx,
6909 architecture, drivers[i],
6910 version, &driver);
6911 if (!W_ERROR_IS_OK(result)) {
6912 goto out;
6915 switch (level) {
6916 case 1:
6917 result = fill_printer_driver_info1(info, &info[count+i].info1,
6918 driver, servername);
6919 break;
6920 case 2:
6921 result = fill_printer_driver_info2(info, &info[count+i].info2,
6922 driver, servername);
6923 break;
6924 case 3:
6925 result = fill_printer_driver_info3(info, &info[count+i].info3,
6926 driver, servername);
6927 break;
6928 case 4:
6929 result = fill_printer_driver_info4(info, &info[count+i].info4,
6930 driver, servername);
6931 break;
6932 case 5:
6933 result = fill_printer_driver_info5(info, &info[count+i].info5,
6934 driver, servername);
6935 break;
6936 case 6:
6937 result = fill_printer_driver_info6(info, &info[count+i].info6,
6938 driver, servername);
6939 break;
6940 case 8:
6941 result = fill_printer_driver_info8(info, &info[count+i].info8,
6942 driver, servername);
6943 break;
6944 default:
6945 result = WERR_UNKNOWN_LEVEL;
6946 break;
6949 TALLOC_FREE(driver);
6951 if (!W_ERROR_IS_OK(result)) {
6952 goto out;
6956 count += num_drivers;
6957 TALLOC_FREE(drivers);
6960 out:
6961 TALLOC_FREE(drivers);
6963 if (!W_ERROR_IS_OK(result)) {
6964 TALLOC_FREE(info);
6965 return result;
6968 *info_p = info;
6969 *count_p = count;
6971 return WERR_OK;
6974 /****************************************************************************
6975 Enumerates all printer drivers by level.
6976 ****************************************************************************/
6978 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
6979 struct auth_serversupplied_info *server_info,
6980 struct messaging_context *msg_ctx,
6981 const char *servername,
6982 const char *architecture,
6983 uint32_t level,
6984 union spoolss_DriverInfo **info_p,
6985 uint32_t *count_p)
6987 uint32_t a,i;
6988 WERROR result = WERR_OK;
6990 if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
6992 for (a=0; archi_table[a].long_archi != NULL; a++) {
6994 union spoolss_DriverInfo *info = NULL;
6995 uint32_t count = 0;
6997 result = enumprinterdrivers_level_by_architecture(mem_ctx,
6998 server_info,
6999 msg_ctx,
7000 servername,
7001 archi_table[a].long_archi,
7002 level,
7003 &info,
7004 &count);
7005 if (!W_ERROR_IS_OK(result)) {
7006 continue;
7009 for (i=0; i < count; i++) {
7010 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7011 info[i], info_p, count_p);
7015 return result;
7018 return enumprinterdrivers_level_by_architecture(mem_ctx,
7019 server_info,
7020 msg_ctx,
7021 servername,
7022 architecture,
7023 level,
7024 info_p,
7025 count_p);
7028 /****************************************************************
7029 _spoolss_EnumPrinterDrivers
7030 ****************************************************************/
7032 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7033 struct spoolss_EnumPrinterDrivers *r)
7035 const char *cservername;
7036 WERROR result;
7038 /* that's an [in out] buffer */
7040 if (!r->in.buffer && (r->in.offered != 0)) {
7041 return WERR_INVALID_PARAM;
7044 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7046 *r->out.needed = 0;
7047 *r->out.count = 0;
7048 *r->out.info = NULL;
7050 cservername = canon_servername(r->in.server);
7052 if (!is_myname_or_ipaddr(cservername)) {
7053 return WERR_UNKNOWN_PRINTER_DRIVER;
7056 result = enumprinterdrivers_level(p->mem_ctx,
7057 p->server_info,
7058 p->msg_ctx,
7059 cservername,
7060 r->in.environment,
7061 r->in.level,
7062 r->out.info,
7063 r->out.count);
7064 if (!W_ERROR_IS_OK(result)) {
7065 return result;
7068 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7069 spoolss_EnumPrinterDrivers,
7070 *r->out.info, r->in.level,
7071 *r->out.count);
7072 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7073 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7075 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7078 /****************************************************************
7079 _spoolss_EnumForms
7080 ****************************************************************/
7082 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7083 struct spoolss_EnumForms *r)
7085 WERROR result;
7087 *r->out.count = 0;
7088 *r->out.needed = 0;
7089 *r->out.info = NULL;
7091 /* that's an [in out] buffer */
7093 if (!r->in.buffer && (r->in.offered != 0) ) {
7094 return WERR_INVALID_PARAM;
7097 DEBUG(4,("_spoolss_EnumForms\n"));
7098 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7099 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7101 switch (r->in.level) {
7102 case 1:
7103 result = winreg_printer_enumforms1(p->mem_ctx,
7104 p->server_info,
7105 p->msg_ctx,
7106 r->out.count,
7107 r->out.info);
7108 break;
7109 default:
7110 result = WERR_UNKNOWN_LEVEL;
7111 break;
7114 if (!W_ERROR_IS_OK(result)) {
7115 return result;
7118 if (*r->out.count == 0) {
7119 return WERR_NO_MORE_ITEMS;
7122 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7123 spoolss_EnumForms,
7124 *r->out.info, r->in.level,
7125 *r->out.count);
7126 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7127 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7129 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7132 /****************************************************************
7133 _spoolss_GetForm
7134 ****************************************************************/
7136 WERROR _spoolss_GetForm(struct pipes_struct *p,
7137 struct spoolss_GetForm *r)
7139 WERROR result;
7141 /* that's an [in out] buffer */
7143 if (!r->in.buffer && (r->in.offered != 0)) {
7144 return WERR_INVALID_PARAM;
7147 DEBUG(4,("_spoolss_GetForm\n"));
7148 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7149 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7151 switch (r->in.level) {
7152 case 1:
7153 result = winreg_printer_getform1(p->mem_ctx,
7154 p->server_info,
7155 p->msg_ctx,
7156 r->in.form_name,
7157 &r->out.info->info1);
7158 break;
7159 default:
7160 result = WERR_UNKNOWN_LEVEL;
7161 break;
7164 if (!W_ERROR_IS_OK(result)) {
7165 TALLOC_FREE(r->out.info);
7166 return result;
7169 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
7170 r->out.info, r->in.level);
7171 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7173 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7176 /****************************************************************************
7177 ****************************************************************************/
7179 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7180 struct spoolss_PortInfo1 *r,
7181 const char *name)
7183 r->port_name = talloc_strdup(mem_ctx, name);
7184 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7186 return WERR_OK;
7189 /****************************************************************************
7190 TODO: This probably needs distinguish between TCP/IP and Local ports
7191 somehow.
7192 ****************************************************************************/
7194 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7195 struct spoolss_PortInfo2 *r,
7196 const char *name)
7198 r->port_name = talloc_strdup(mem_ctx, name);
7199 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7201 r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7202 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7204 r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7205 W_ERROR_HAVE_NO_MEMORY(r->description);
7207 r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7208 r->reserved = 0;
7210 return WERR_OK;
7214 /****************************************************************************
7215 wrapper around the enumer ports command
7216 ****************************************************************************/
7218 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7220 char *cmd = lp_enumports_cmd();
7221 char **qlines = NULL;
7222 char *command = NULL;
7223 int numlines;
7224 int ret;
7225 int fd;
7227 *count = 0;
7228 *lines = NULL;
7230 /* if no hook then just fill in the default port */
7232 if ( !*cmd ) {
7233 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7234 return WERR_NOMEM;
7236 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7237 TALLOC_FREE(qlines);
7238 return WERR_NOMEM;
7240 qlines[1] = NULL;
7241 numlines = 1;
7243 else {
7244 /* we have a valid enumport command */
7246 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7247 if (!command) {
7248 return WERR_NOMEM;
7251 DEBUG(10,("Running [%s]\n", command));
7252 ret = smbrun(command, &fd);
7253 DEBUG(10,("Returned [%d]\n", ret));
7254 TALLOC_FREE(command);
7255 if (ret != 0) {
7256 if (fd != -1) {
7257 close(fd);
7259 return WERR_ACCESS_DENIED;
7262 numlines = 0;
7263 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7264 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7265 close(fd);
7268 *count = numlines;
7269 *lines = qlines;
7271 return WERR_OK;
7274 /****************************************************************************
7275 enumports level 1.
7276 ****************************************************************************/
7278 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7279 union spoolss_PortInfo **info_p,
7280 uint32_t *count)
7282 union spoolss_PortInfo *info = NULL;
7283 int i=0;
7284 WERROR result = WERR_OK;
7285 char **qlines = NULL;
7286 int numlines = 0;
7288 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7289 if (!W_ERROR_IS_OK(result)) {
7290 goto out;
7293 if (numlines) {
7294 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7295 if (!info) {
7296 DEBUG(10,("Returning WERR_NOMEM\n"));
7297 result = WERR_NOMEM;
7298 goto out;
7301 for (i=0; i<numlines; i++) {
7302 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7303 result = fill_port_1(info, &info[i].info1, qlines[i]);
7304 if (!W_ERROR_IS_OK(result)) {
7305 goto out;
7309 TALLOC_FREE(qlines);
7311 out:
7312 if (!W_ERROR_IS_OK(result)) {
7313 TALLOC_FREE(info);
7314 TALLOC_FREE(qlines);
7315 *count = 0;
7316 *info_p = NULL;
7317 return result;
7320 *info_p = info;
7321 *count = numlines;
7323 return WERR_OK;
7326 /****************************************************************************
7327 enumports level 2.
7328 ****************************************************************************/
7330 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7331 union spoolss_PortInfo **info_p,
7332 uint32_t *count)
7334 union spoolss_PortInfo *info = NULL;
7335 int i=0;
7336 WERROR result = WERR_OK;
7337 char **qlines = NULL;
7338 int numlines = 0;
7340 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7341 if (!W_ERROR_IS_OK(result)) {
7342 goto out;
7345 if (numlines) {
7346 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7347 if (!info) {
7348 DEBUG(10,("Returning WERR_NOMEM\n"));
7349 result = WERR_NOMEM;
7350 goto out;
7353 for (i=0; i<numlines; i++) {
7354 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7355 result = fill_port_2(info, &info[i].info2, qlines[i]);
7356 if (!W_ERROR_IS_OK(result)) {
7357 goto out;
7361 TALLOC_FREE(qlines);
7363 out:
7364 if (!W_ERROR_IS_OK(result)) {
7365 TALLOC_FREE(info);
7366 TALLOC_FREE(qlines);
7367 *count = 0;
7368 *info_p = NULL;
7369 return result;
7372 *info_p = info;
7373 *count = numlines;
7375 return WERR_OK;
7378 /****************************************************************
7379 _spoolss_EnumPorts
7380 ****************************************************************/
7382 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
7383 struct spoolss_EnumPorts *r)
7385 WERROR result;
7387 /* that's an [in out] buffer */
7389 if (!r->in.buffer && (r->in.offered != 0)) {
7390 return WERR_INVALID_PARAM;
7393 DEBUG(4,("_spoolss_EnumPorts\n"));
7395 *r->out.count = 0;
7396 *r->out.needed = 0;
7397 *r->out.info = NULL;
7399 switch (r->in.level) {
7400 case 1:
7401 result = enumports_level_1(p->mem_ctx, r->out.info,
7402 r->out.count);
7403 break;
7404 case 2:
7405 result = enumports_level_2(p->mem_ctx, r->out.info,
7406 r->out.count);
7407 break;
7408 default:
7409 return WERR_UNKNOWN_LEVEL;
7412 if (!W_ERROR_IS_OK(result)) {
7413 return result;
7416 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7417 spoolss_EnumPorts,
7418 *r->out.info, r->in.level,
7419 *r->out.count);
7420 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7421 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7423 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7426 /****************************************************************************
7427 ****************************************************************************/
7429 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
7430 const char *server,
7431 struct spoolss_SetPrinterInfoCtr *info_ctr,
7432 struct spoolss_DeviceMode *devmode,
7433 struct security_descriptor *secdesc,
7434 struct spoolss_UserLevelCtr *user_ctr,
7435 struct policy_handle *handle)
7437 struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
7438 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
7439 int snum;
7440 WERROR err = WERR_OK;
7442 /* samba does not have a concept of local, non-shared printers yet, so
7443 * make sure we always setup sharename - gd */
7444 if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
7445 (info2->printername != NULL && info2->printername[0] != '\0')) {
7446 DEBUG(5, ("spoolss_addprinterex_level_2: "
7447 "no sharename has been set, setting printername %s as sharename\n",
7448 info2->printername));
7449 info2->sharename = info2->printername;
7452 /* check to see if the printer already exists */
7453 if ((snum = print_queue_snum(info2->sharename)) != -1) {
7454 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7455 info2->sharename));
7456 return WERR_PRINTER_ALREADY_EXISTS;
7459 if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7460 if ((snum = print_queue_snum(info2->printername)) != -1) {
7461 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7462 info2->printername));
7463 return WERR_PRINTER_ALREADY_EXISTS;
7467 /* validate printer info struct */
7468 if (!info2->printername || strlen(info2->printername) == 0) {
7469 return WERR_INVALID_PRINTER_NAME;
7471 if (!info2->portname || strlen(info2->portname) == 0) {
7472 return WERR_UNKNOWN_PORT;
7474 if (!info2->drivername || strlen(info2->drivername) == 0) {
7475 return WERR_UNKNOWN_PRINTER_DRIVER;
7477 if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
7478 return WERR_UNKNOWN_PRINTPROCESSOR;
7481 /* FIXME!!! smbd should check to see if the driver is installed before
7482 trying to add a printer like this --jerry */
7484 if (*lp_addprinter_cmd() ) {
7485 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7486 info2, p->client_id->addr,
7487 p->msg_ctx) ) {
7488 return WERR_ACCESS_DENIED;
7490 } else {
7491 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7492 "smb.conf parameter \"addprinter command\" is defined. This"
7493 "parameter must exist for this call to succeed\n",
7494 info2->sharename ));
7497 if ((snum = print_queue_snum(info2->sharename)) == -1) {
7498 return WERR_ACCESS_DENIED;
7501 /* you must be a printer admin to add a new printer */
7502 if (!print_access_check(p->server_info, p->msg_ctx, snum,
7503 PRINTER_ACCESS_ADMINISTER)) {
7504 return WERR_ACCESS_DENIED;
7508 * Do sanity check on the requested changes for Samba.
7511 if (!check_printer_ok(p->mem_ctx, info2, snum)) {
7512 return WERR_INVALID_PARAM;
7515 if (devmode == NULL) {
7516 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
7519 update_dsspooler(p->mem_ctx,
7520 p->server_info,
7521 p->msg_ctx,
7523 info2,
7524 NULL);
7526 err = winreg_update_printer(p->mem_ctx,
7527 p->server_info,
7528 p->msg_ctx,
7529 info2->sharename,
7530 info2_mask,
7531 info2,
7532 devmode,
7533 secdesc);
7534 if (!W_ERROR_IS_OK(err)) {
7535 return err;
7538 if (!open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER)) {
7539 /* Handle open failed - remove addition. */
7540 ZERO_STRUCTP(handle);
7541 return WERR_ACCESS_DENIED;
7544 return WERR_OK;
7547 /****************************************************************
7548 _spoolss_AddPrinterEx
7549 ****************************************************************/
7551 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
7552 struct spoolss_AddPrinterEx *r)
7554 switch (r->in.info_ctr->level) {
7555 case 1:
7556 /* we don't handle yet */
7557 /* but I know what to do ... */
7558 return WERR_UNKNOWN_LEVEL;
7559 case 2:
7560 return spoolss_addprinterex_level_2(p, r->in.server,
7561 r->in.info_ctr,
7562 r->in.devmode_ctr->devmode,
7563 r->in.secdesc_ctr->sd,
7564 r->in.userlevel_ctr,
7565 r->out.handle);
7566 default:
7567 return WERR_UNKNOWN_LEVEL;
7571 /****************************************************************
7572 _spoolss_AddPrinter
7573 ****************************************************************/
7575 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
7576 struct spoolss_AddPrinter *r)
7578 struct spoolss_AddPrinterEx a;
7579 struct spoolss_UserLevelCtr userlevel_ctr;
7581 ZERO_STRUCT(userlevel_ctr);
7583 userlevel_ctr.level = 1;
7585 a.in.server = r->in.server;
7586 a.in.info_ctr = r->in.info_ctr;
7587 a.in.devmode_ctr = r->in.devmode_ctr;
7588 a.in.secdesc_ctr = r->in.secdesc_ctr;
7589 a.in.userlevel_ctr = &userlevel_ctr;
7590 a.out.handle = r->out.handle;
7592 return _spoolss_AddPrinterEx(p, &a);
7595 /****************************************************************
7596 _spoolss_AddPrinterDriverEx
7597 ****************************************************************/
7599 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
7600 struct spoolss_AddPrinterDriverEx *r)
7602 WERROR err = WERR_OK;
7603 const char *driver_name = NULL;
7604 uint32_t version;
7605 const char *fn;
7607 switch (p->opnum) {
7608 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7609 fn = "_spoolss_AddPrinterDriver";
7610 break;
7611 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7612 fn = "_spoolss_AddPrinterDriverEx";
7613 break;
7614 default:
7615 return WERR_INVALID_PARAM;
7619 * we only support the semantics of AddPrinterDriver()
7620 * i.e. only copy files that are newer than existing ones
7623 if (r->in.flags == 0) {
7624 return WERR_INVALID_PARAM;
7627 if (r->in.flags != APD_COPY_NEW_FILES) {
7628 return WERR_ACCESS_DENIED;
7631 /* FIXME */
7632 if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
7633 /* Clever hack from Martin Zielinski <mz@seh.de>
7634 * to allow downgrade from level 8 (Vista).
7636 DEBUG(0,("%s: level %d not yet implemented\n", fn,
7637 r->in.info_ctr->level));
7638 return WERR_UNKNOWN_LEVEL;
7641 DEBUG(5,("Cleaning driver's information\n"));
7642 err = clean_up_driver_struct(p->mem_ctx, p, r->in.info_ctr);
7643 if (!W_ERROR_IS_OK(err))
7644 goto done;
7646 DEBUG(5,("Moving driver to final destination\n"));
7647 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, r->in.info_ctr,
7648 &err)) ) {
7649 goto done;
7652 err = winreg_add_driver(p->mem_ctx, p->server_info, p->msg_ctx,
7653 r->in.info_ctr, &driver_name, &version);
7654 if (!W_ERROR_IS_OK(err)) {
7655 goto done;
7659 * I think this is where he DrvUpgradePrinter() hook would be
7660 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7661 * server. Right now, we just need to send ourselves a message
7662 * to update each printer bound to this driver. --jerry
7665 if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
7666 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7667 fn, driver_name));
7670 done:
7671 return err;
7674 /****************************************************************
7675 _spoolss_AddPrinterDriver
7676 ****************************************************************/
7678 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
7679 struct spoolss_AddPrinterDriver *r)
7681 struct spoolss_AddPrinterDriverEx a;
7683 switch (r->in.info_ctr->level) {
7684 case 2:
7685 case 3:
7686 case 4:
7687 case 5:
7688 break;
7689 default:
7690 return WERR_UNKNOWN_LEVEL;
7693 a.in.servername = r->in.servername;
7694 a.in.info_ctr = r->in.info_ctr;
7695 a.in.flags = APD_COPY_NEW_FILES;
7697 return _spoolss_AddPrinterDriverEx(p, &a);
7700 /****************************************************************************
7701 ****************************************************************************/
7703 struct _spoolss_paths {
7704 int type;
7705 const char *share;
7706 const char *dir;
7709 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
7711 static const struct _spoolss_paths spoolss_paths[]= {
7712 { SPOOLSS_DRIVER_PATH, "print$", "DRIVERS" },
7713 { SPOOLSS_PRTPROCS_PATH, "prnproc$", "PRTPROCS" }
7716 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
7717 const char *servername,
7718 const char *environment,
7719 int component,
7720 char **path)
7722 const char *pservername = NULL;
7723 const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
7724 const char *short_archi;
7726 *path = NULL;
7728 /* environment may be empty */
7729 if (environment && strlen(environment)) {
7730 long_archi = environment;
7733 /* servername may be empty */
7734 if (servername && strlen(servername)) {
7735 pservername = canon_servername(servername);
7737 if (!is_myname_or_ipaddr(pservername)) {
7738 return WERR_INVALID_PARAM;
7742 if (!(short_archi = get_short_archi(long_archi))) {
7743 return WERR_INVALID_ENVIRONMENT;
7746 switch (component) {
7747 case SPOOLSS_PRTPROCS_PATH:
7748 case SPOOLSS_DRIVER_PATH:
7749 if (pservername) {
7750 *path = talloc_asprintf(mem_ctx,
7751 "\\\\%s\\%s\\%s",
7752 pservername,
7753 spoolss_paths[component].share,
7754 short_archi);
7755 } else {
7756 *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
7757 SPOOLSS_DEFAULT_SERVER_PATH,
7758 spoolss_paths[component].dir,
7759 short_archi);
7761 break;
7762 default:
7763 return WERR_INVALID_PARAM;
7766 if (!*path) {
7767 return WERR_NOMEM;
7770 return WERR_OK;
7773 /****************************************************************************
7774 ****************************************************************************/
7776 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
7777 const char *servername,
7778 const char *environment,
7779 struct spoolss_DriverDirectoryInfo1 *r)
7781 WERROR werr;
7782 char *path = NULL;
7784 werr = compose_spoolss_server_path(mem_ctx,
7785 servername,
7786 environment,
7787 SPOOLSS_DRIVER_PATH,
7788 &path);
7789 if (!W_ERROR_IS_OK(werr)) {
7790 return werr;
7793 DEBUG(4,("printer driver directory: [%s]\n", path));
7795 r->directory_name = path;
7797 return WERR_OK;
7800 /****************************************************************
7801 _spoolss_GetPrinterDriverDirectory
7802 ****************************************************************/
7804 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
7805 struct spoolss_GetPrinterDriverDirectory *r)
7807 WERROR werror;
7809 /* that's an [in out] buffer */
7811 if (!r->in.buffer && (r->in.offered != 0)) {
7812 return WERR_INVALID_PARAM;
7815 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
7816 r->in.level));
7818 *r->out.needed = 0;
7820 /* r->in.level is ignored */
7822 werror = getprinterdriverdir_level_1(p->mem_ctx,
7823 r->in.server,
7824 r->in.environment,
7825 &r->out.info->info1);
7826 if (!W_ERROR_IS_OK(werror)) {
7827 TALLOC_FREE(r->out.info);
7828 return werror;
7831 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
7832 r->out.info, r->in.level);
7833 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7835 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7838 /****************************************************************
7839 _spoolss_EnumPrinterData
7840 ****************************************************************/
7842 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
7843 struct spoolss_EnumPrinterData *r)
7845 WERROR result;
7846 struct spoolss_EnumPrinterDataEx r2;
7847 uint32_t count;
7848 struct spoolss_PrinterEnumValues *info, *val = NULL;
7849 uint32_t needed;
7851 r2.in.handle = r->in.handle;
7852 r2.in.key_name = "PrinterDriverData";
7853 r2.in.offered = 0;
7854 r2.out.count = &count;
7855 r2.out.info = &info;
7856 r2.out.needed = &needed;
7858 result = _spoolss_EnumPrinterDataEx(p, &r2);
7859 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
7860 r2.in.offered = needed;
7861 result = _spoolss_EnumPrinterDataEx(p, &r2);
7863 if (!W_ERROR_IS_OK(result)) {
7864 return result;
7868 * The NT machine wants to know the biggest size of value and data
7870 * cf: MSDN EnumPrinterData remark section
7873 if (!r->in.value_offered && !r->in.data_offered) {
7874 uint32_t biggest_valuesize = 0;
7875 uint32_t biggest_datasize = 0;
7876 int i, name_length;
7878 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7880 for (i=0; i<count; i++) {
7882 name_length = strlen(info[i].value_name);
7883 if (strlen(info[i].value_name) > biggest_valuesize) {
7884 biggest_valuesize = name_length;
7887 if (info[i].data_length > biggest_datasize) {
7888 biggest_datasize = info[i].data_length;
7891 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
7892 biggest_datasize));
7895 /* the value is an UNICODE string but real_value_size is the length
7896 in bytes including the trailing 0 */
7898 *r->out.value_needed = 2 * (1 + biggest_valuesize);
7899 *r->out.data_needed = biggest_datasize;
7901 DEBUG(6,("final values: [%d], [%d]\n",
7902 *r->out.value_needed, *r->out.data_needed));
7904 return WERR_OK;
7907 if (r->in.enum_index < count) {
7908 val = &info[r->in.enum_index];
7911 if (val == NULL) {
7912 /* out_value should default to "" or else NT4 has
7913 problems unmarshalling the response */
7915 if (r->in.value_offered) {
7916 *r->out.value_needed = 1;
7917 r->out.value_name = talloc_strdup(r, "");
7918 if (!r->out.value_name) {
7919 return WERR_NOMEM;
7921 } else {
7922 r->out.value_name = NULL;
7923 *r->out.value_needed = 0;
7926 /* the data is counted in bytes */
7928 *r->out.data_needed = r->in.data_offered;
7930 result = WERR_NO_MORE_ITEMS;
7931 } else {
7933 * the value is:
7934 * - counted in bytes in the request
7935 * - counted in UNICODE chars in the max reply
7936 * - counted in bytes in the real size
7938 * take a pause *before* coding not *during* coding
7941 /* name */
7942 if (r->in.value_offered) {
7943 r->out.value_name = talloc_strdup(r, val->value_name);
7944 if (!r->out.value_name) {
7945 return WERR_NOMEM;
7947 *r->out.value_needed = val->value_name_len;
7948 } else {
7949 r->out.value_name = NULL;
7950 *r->out.value_needed = 0;
7953 /* type */
7955 *r->out.type = val->type;
7957 /* data - counted in bytes */
7960 * See the section "Dynamically Typed Query Parameters"
7961 * in MS-RPRN.
7964 if (r->out.data && val->data && val->data->data &&
7965 val->data_length && r->in.data_offered) {
7966 memcpy(r->out.data, val->data->data,
7967 MIN(val->data_length,r->in.data_offered));
7970 *r->out.data_needed = val->data_length;
7972 result = WERR_OK;
7975 return result;
7978 /****************************************************************
7979 _spoolss_SetPrinterData
7980 ****************************************************************/
7982 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
7983 struct spoolss_SetPrinterData *r)
7985 struct spoolss_SetPrinterDataEx r2;
7987 r2.in.handle = r->in.handle;
7988 r2.in.key_name = "PrinterDriverData";
7989 r2.in.value_name = r->in.value_name;
7990 r2.in.type = r->in.type;
7991 r2.in.data = r->in.data;
7992 r2.in.offered = r->in.offered;
7994 return _spoolss_SetPrinterDataEx(p, &r2);
7997 /****************************************************************
7998 _spoolss_ResetPrinter
7999 ****************************************************************/
8001 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8002 struct spoolss_ResetPrinter *r)
8004 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8005 int snum;
8007 DEBUG(5,("_spoolss_ResetPrinter\n"));
8010 * All we do is to check to see if the handle and queue is valid.
8011 * This call really doesn't mean anything to us because we only
8012 * support RAW printing. --jerry
8015 if (!Printer) {
8016 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8017 OUR_HANDLE(r->in.handle)));
8018 return WERR_BADFID;
8021 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8022 return WERR_BADFID;
8025 /* blindly return success */
8026 return WERR_OK;
8029 /****************************************************************
8030 _spoolss_DeletePrinterData
8031 ****************************************************************/
8033 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8034 struct spoolss_DeletePrinterData *r)
8036 struct spoolss_DeletePrinterDataEx r2;
8038 r2.in.handle = r->in.handle;
8039 r2.in.key_name = "PrinterDriverData";
8040 r2.in.value_name = r->in.value_name;
8042 return _spoolss_DeletePrinterDataEx(p, &r2);
8045 /****************************************************************
8046 _spoolss_AddForm
8047 ****************************************************************/
8049 WERROR _spoolss_AddForm(struct pipes_struct *p,
8050 struct spoolss_AddForm *r)
8052 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8053 int snum = -1;
8054 WERROR status = WERR_OK;
8055 SE_PRIV se_printop = SE_PRINT_OPERATOR;
8057 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8059 DEBUG(5,("_spoolss_AddForm\n"));
8061 if (!Printer) {
8062 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8063 OUR_HANDLE(r->in.handle)));
8064 return WERR_BADFID;
8067 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8068 and not a printer admin, then fail */
8070 if ((p->server_info->utok.uid != sec_initial_uid()) &&
8071 !user_has_privileges(p->server_info->ptok, &se_printop) &&
8072 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8073 p->server_info->info3->base.domain.string,
8074 NULL,
8075 p->server_info->ptok,
8076 lp_printer_admin(snum))) {
8077 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8078 return WERR_ACCESS_DENIED;
8081 switch (form->flags) {
8082 case SPOOLSS_FORM_USER:
8083 case SPOOLSS_FORM_BUILTIN:
8084 case SPOOLSS_FORM_PRINTER:
8085 break;
8086 default:
8087 return WERR_INVALID_PARAM;
8090 status = winreg_printer_addform1(p->mem_ctx, p->server_info,
8091 p->msg_ctx, form);
8092 if (!W_ERROR_IS_OK(status)) {
8093 return status;
8097 * ChangeID must always be set if this is a printer
8099 if (Printer->printer_type == SPLHND_PRINTER) {
8100 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8101 return WERR_BADFID;
8104 status = winreg_printer_update_changeid(p->mem_ctx,
8105 p->server_info,
8106 p->msg_ctx,
8107 lp_const_servicename(snum));
8108 if (!W_ERROR_IS_OK(status)) {
8109 return status;
8113 return status;
8116 /****************************************************************
8117 _spoolss_DeleteForm
8118 ****************************************************************/
8120 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8121 struct spoolss_DeleteForm *r)
8123 const char *form_name = r->in.form_name;
8124 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8125 int snum = -1;
8126 WERROR status = WERR_OK;
8127 SE_PRIV se_printop = SE_PRINT_OPERATOR;
8129 DEBUG(5,("_spoolss_DeleteForm\n"));
8131 if (!Printer) {
8132 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8133 OUR_HANDLE(r->in.handle)));
8134 return WERR_BADFID;
8137 if ((p->server_info->utok.uid != sec_initial_uid()) &&
8138 !user_has_privileges(p->server_info->ptok, &se_printop) &&
8139 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8140 p->server_info->info3->base.domain.string,
8141 NULL,
8142 p->server_info->ptok,
8143 lp_printer_admin(snum))) {
8144 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8145 return WERR_ACCESS_DENIED;
8148 status = winreg_printer_deleteform1(p->mem_ctx,
8149 p->server_info,
8150 p->msg_ctx,
8151 form_name);
8152 if (!W_ERROR_IS_OK(status)) {
8153 return status;
8157 * ChangeID must always be set if this is a printer
8159 if (Printer->printer_type == SPLHND_PRINTER) {
8160 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8161 return WERR_BADFID;
8164 status = winreg_printer_update_changeid(p->mem_ctx,
8165 p->server_info,
8166 p->msg_ctx,
8167 lp_const_servicename(snum));
8168 if (!W_ERROR_IS_OK(status)) {
8169 return status;
8173 return status;
8176 /****************************************************************
8177 _spoolss_SetForm
8178 ****************************************************************/
8180 WERROR _spoolss_SetForm(struct pipes_struct *p,
8181 struct spoolss_SetForm *r)
8183 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8184 const char *form_name = r->in.form_name;
8185 int snum = -1;
8186 WERROR status = WERR_OK;
8187 SE_PRIV se_printop = SE_PRINT_OPERATOR;
8189 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8191 DEBUG(5,("_spoolss_SetForm\n"));
8193 if (!Printer) {
8194 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8195 OUR_HANDLE(r->in.handle)));
8196 return WERR_BADFID;
8199 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8200 and not a printer admin, then fail */
8202 if ((p->server_info->utok.uid != sec_initial_uid()) &&
8203 !user_has_privileges(p->server_info->ptok, &se_printop) &&
8204 !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8205 p->server_info->info3->base.domain.string,
8206 NULL,
8207 p->server_info->ptok,
8208 lp_printer_admin(snum))) {
8209 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8210 return WERR_ACCESS_DENIED;
8213 status = winreg_printer_setform1(p->mem_ctx,
8214 p->server_info,
8215 p->msg_ctx,
8216 form_name,
8217 form);
8218 if (!W_ERROR_IS_OK(status)) {
8219 return status;
8223 * ChangeID must always be set if this is a printer
8225 if (Printer->printer_type == SPLHND_PRINTER) {
8226 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8227 return WERR_BADFID;
8230 status = winreg_printer_update_changeid(p->mem_ctx,
8231 p->server_info,
8232 p->msg_ctx,
8233 lp_const_servicename(snum));
8234 if (!W_ERROR_IS_OK(status)) {
8235 return status;
8239 return status;
8242 /****************************************************************************
8243 fill_print_processor1
8244 ****************************************************************************/
8246 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8247 struct spoolss_PrintProcessorInfo1 *r,
8248 const char *print_processor_name)
8250 r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8251 W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8253 return WERR_OK;
8256 /****************************************************************************
8257 enumprintprocessors level 1.
8258 ****************************************************************************/
8260 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8261 union spoolss_PrintProcessorInfo **info_p,
8262 uint32_t *count)
8264 union spoolss_PrintProcessorInfo *info;
8265 WERROR result;
8267 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8268 W_ERROR_HAVE_NO_MEMORY(info);
8270 *count = 1;
8272 result = fill_print_processor1(info, &info[0].info1, "winprint");
8273 if (!W_ERROR_IS_OK(result)) {
8274 goto out;
8277 out:
8278 if (!W_ERROR_IS_OK(result)) {
8279 TALLOC_FREE(info);
8280 *count = 0;
8281 return result;
8284 *info_p = info;
8286 return WERR_OK;
8289 /****************************************************************
8290 _spoolss_EnumPrintProcessors
8291 ****************************************************************/
8293 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
8294 struct spoolss_EnumPrintProcessors *r)
8296 WERROR result;
8298 /* that's an [in out] buffer */
8300 if (!r->in.buffer && (r->in.offered != 0)) {
8301 return WERR_INVALID_PARAM;
8304 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8307 * Enumerate the print processors ...
8309 * Just reply with "winprint", to keep NT happy
8310 * and I can use my nice printer checker.
8313 *r->out.count = 0;
8314 *r->out.needed = 0;
8315 *r->out.info = NULL;
8317 switch (r->in.level) {
8318 case 1:
8319 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8320 r->out.count);
8321 break;
8322 default:
8323 return WERR_UNKNOWN_LEVEL;
8326 if (!W_ERROR_IS_OK(result)) {
8327 return result;
8330 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8331 spoolss_EnumPrintProcessors,
8332 *r->out.info, r->in.level,
8333 *r->out.count);
8334 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8335 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8337 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8340 /****************************************************************************
8341 fill_printprocdatatype1
8342 ****************************************************************************/
8344 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8345 struct spoolss_PrintProcDataTypesInfo1 *r,
8346 const char *name_array)
8348 r->name_array = talloc_strdup(mem_ctx, name_array);
8349 W_ERROR_HAVE_NO_MEMORY(r->name_array);
8351 return WERR_OK;
8354 /****************************************************************************
8355 enumprintprocdatatypes level 1.
8356 ****************************************************************************/
8358 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8359 union spoolss_PrintProcDataTypesInfo **info_p,
8360 uint32_t *count)
8362 WERROR result;
8363 union spoolss_PrintProcDataTypesInfo *info;
8365 info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8366 W_ERROR_HAVE_NO_MEMORY(info);
8368 *count = 1;
8370 result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8371 if (!W_ERROR_IS_OK(result)) {
8372 goto out;
8375 out:
8376 if (!W_ERROR_IS_OK(result)) {
8377 TALLOC_FREE(info);
8378 *count = 0;
8379 return result;
8382 *info_p = info;
8384 return WERR_OK;
8387 /****************************************************************
8388 _spoolss_EnumPrintProcDataTypes
8389 ****************************************************************/
8391 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
8392 struct spoolss_EnumPrintProcDataTypes *r)
8394 WERROR result;
8396 /* that's an [in out] buffer */
8398 if (!r->in.buffer && (r->in.offered != 0)) {
8399 return WERR_INVALID_PARAM;
8402 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8404 *r->out.count = 0;
8405 *r->out.needed = 0;
8406 *r->out.info = NULL;
8408 switch (r->in.level) {
8409 case 1:
8410 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8411 r->out.count);
8412 break;
8413 default:
8414 return WERR_UNKNOWN_LEVEL;
8417 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8418 spoolss_EnumPrintProcDataTypes,
8419 *r->out.info, r->in.level,
8420 *r->out.count);
8421 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8422 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8424 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8427 /****************************************************************************
8428 fill_monitor_1
8429 ****************************************************************************/
8431 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8432 struct spoolss_MonitorInfo1 *r,
8433 const char *monitor_name)
8435 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8436 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8438 return WERR_OK;
8441 /****************************************************************************
8442 fill_monitor_2
8443 ****************************************************************************/
8445 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8446 struct spoolss_MonitorInfo2 *r,
8447 const char *monitor_name,
8448 const char *environment,
8449 const char *dll_name)
8451 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8452 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8453 r->environment = talloc_strdup(mem_ctx, environment);
8454 W_ERROR_HAVE_NO_MEMORY(r->environment);
8455 r->dll_name = talloc_strdup(mem_ctx, dll_name);
8456 W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8458 return WERR_OK;
8461 /****************************************************************************
8462 enumprintmonitors level 1.
8463 ****************************************************************************/
8465 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8466 union spoolss_MonitorInfo **info_p,
8467 uint32_t *count)
8469 union spoolss_MonitorInfo *info;
8470 WERROR result = WERR_OK;
8472 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8473 W_ERROR_HAVE_NO_MEMORY(info);
8475 *count = 2;
8477 result = fill_monitor_1(info, &info[0].info1,
8478 SPL_LOCAL_PORT);
8479 if (!W_ERROR_IS_OK(result)) {
8480 goto out;
8483 result = fill_monitor_1(info, &info[1].info1,
8484 SPL_TCPIP_PORT);
8485 if (!W_ERROR_IS_OK(result)) {
8486 goto out;
8489 out:
8490 if (!W_ERROR_IS_OK(result)) {
8491 TALLOC_FREE(info);
8492 *count = 0;
8493 return result;
8496 *info_p = info;
8498 return WERR_OK;
8501 /****************************************************************************
8502 enumprintmonitors level 2.
8503 ****************************************************************************/
8505 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8506 union spoolss_MonitorInfo **info_p,
8507 uint32_t *count)
8509 union spoolss_MonitorInfo *info;
8510 WERROR result = WERR_OK;
8512 info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8513 W_ERROR_HAVE_NO_MEMORY(info);
8515 *count = 2;
8517 result = fill_monitor_2(info, &info[0].info2,
8518 SPL_LOCAL_PORT,
8519 "Windows NT X86", /* FIXME */
8520 "localmon.dll");
8521 if (!W_ERROR_IS_OK(result)) {
8522 goto out;
8525 result = fill_monitor_2(info, &info[1].info2,
8526 SPL_TCPIP_PORT,
8527 "Windows NT X86", /* FIXME */
8528 "tcpmon.dll");
8529 if (!W_ERROR_IS_OK(result)) {
8530 goto out;
8533 out:
8534 if (!W_ERROR_IS_OK(result)) {
8535 TALLOC_FREE(info);
8536 *count = 0;
8537 return result;
8540 *info_p = info;
8542 return WERR_OK;
8545 /****************************************************************
8546 _spoolss_EnumMonitors
8547 ****************************************************************/
8549 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
8550 struct spoolss_EnumMonitors *r)
8552 WERROR result;
8554 /* that's an [in out] buffer */
8556 if (!r->in.buffer && (r->in.offered != 0)) {
8557 return WERR_INVALID_PARAM;
8560 DEBUG(5,("_spoolss_EnumMonitors\n"));
8563 * Enumerate the print monitors ...
8565 * Just reply with "Local Port", to keep NT happy
8566 * and I can use my nice printer checker.
8569 *r->out.count = 0;
8570 *r->out.needed = 0;
8571 *r->out.info = NULL;
8573 switch (r->in.level) {
8574 case 1:
8575 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8576 r->out.count);
8577 break;
8578 case 2:
8579 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8580 r->out.count);
8581 break;
8582 default:
8583 return WERR_UNKNOWN_LEVEL;
8586 if (!W_ERROR_IS_OK(result)) {
8587 return result;
8590 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8591 spoolss_EnumMonitors,
8592 *r->out.info, r->in.level,
8593 *r->out.count);
8594 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8595 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8597 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8600 /****************************************************************************
8601 ****************************************************************************/
8603 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8604 const print_queue_struct *queue,
8605 int count, int snum,
8606 struct spoolss_PrinterInfo2 *pinfo2,
8607 uint32_t jobid,
8608 struct spoolss_JobInfo1 *r)
8610 int i = 0;
8611 bool found = false;
8613 for (i=0; i<count; i++) {
8614 if (queue[i].job == (int)jobid) {
8615 found = true;
8616 break;
8620 if (found == false) {
8621 /* NT treats not found as bad param... yet another bad choice */
8622 return WERR_INVALID_PARAM;
8625 return fill_job_info1(mem_ctx,
8627 &queue[i],
8629 snum,
8630 pinfo2);
8633 /****************************************************************************
8634 ****************************************************************************/
8636 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
8637 const print_queue_struct *queue,
8638 int count, int snum,
8639 struct spoolss_PrinterInfo2 *pinfo2,
8640 uint32_t jobid,
8641 struct spoolss_JobInfo2 *r)
8643 int i = 0;
8644 bool found = false;
8645 struct spoolss_DeviceMode *devmode;
8646 WERROR result;
8648 for (i=0; i<count; i++) {
8649 if (queue[i].job == (int)jobid) {
8650 found = true;
8651 break;
8655 if (found == false) {
8656 /* NT treats not found as bad param... yet another bad
8657 choice */
8658 return WERR_INVALID_PARAM;
8662 * if the print job does not have a DEVMODE associated with it,
8663 * just use the one for the printer. A NULL devicemode is not
8664 * a failure condition
8667 devmode = print_job_devmode(lp_const_servicename(snum), jobid);
8668 if (!devmode) {
8669 result = spoolss_create_default_devmode(mem_ctx,
8670 pinfo2->printername,
8671 &devmode);
8672 if (!W_ERROR_IS_OK(result)) {
8673 DEBUG(3, ("Can't proceed w/o a devmode!"));
8674 return result;
8678 return fill_job_info2(mem_ctx,
8680 &queue[i],
8682 snum,
8683 pinfo2,
8684 devmode);
8687 /****************************************************************
8688 _spoolss_GetJob
8689 ****************************************************************/
8691 WERROR _spoolss_GetJob(struct pipes_struct *p,
8692 struct spoolss_GetJob *r)
8694 WERROR result = WERR_OK;
8695 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
8696 int snum;
8697 int count;
8698 print_queue_struct *queue = NULL;
8699 print_status_struct prt_status;
8701 /* that's an [in out] buffer */
8703 if (!r->in.buffer && (r->in.offered != 0)) {
8704 return WERR_INVALID_PARAM;
8707 DEBUG(5,("_spoolss_GetJob\n"));
8709 *r->out.needed = 0;
8711 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8712 return WERR_BADFID;
8715 result = winreg_get_printer(p->mem_ctx, p->server_info, p->msg_ctx,
8716 NULL, lp_servicename(snum), &pinfo2);
8717 if (!W_ERROR_IS_OK(result)) {
8718 return result;
8721 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
8723 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8724 count, prt_status.status, prt_status.message));
8726 switch (r->in.level) {
8727 case 1:
8728 result = getjob_level_1(p->mem_ctx,
8729 queue, count, snum, pinfo2,
8730 r->in.job_id, &r->out.info->info1);
8731 break;
8732 case 2:
8733 result = getjob_level_2(p->mem_ctx,
8734 queue, count, snum, pinfo2,
8735 r->in.job_id, &r->out.info->info2);
8736 break;
8737 default:
8738 result = WERR_UNKNOWN_LEVEL;
8739 break;
8742 SAFE_FREE(queue);
8743 TALLOC_FREE(pinfo2);
8745 if (!W_ERROR_IS_OK(result)) {
8746 TALLOC_FREE(r->out.info);
8747 return result;
8750 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
8751 r->in.level);
8752 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8754 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8757 /****************************************************************
8758 _spoolss_GetPrinterDataEx
8759 ****************************************************************/
8761 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
8762 struct spoolss_GetPrinterDataEx *r)
8765 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8766 const char *printer;
8767 int snum = 0;
8768 WERROR result = WERR_OK;
8769 DATA_BLOB blob;
8770 enum winreg_Type val_type;
8771 uint8_t *val_data;
8772 uint32_t val_size;
8775 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
8777 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
8778 r->in.key_name, r->in.value_name));
8780 /* in case of problem, return some default values */
8782 *r->out.needed = 0;
8783 *r->out.type = REG_NONE;
8785 if (!Printer) {
8786 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8787 OUR_HANDLE(r->in.handle)));
8788 result = WERR_BADFID;
8789 goto done;
8792 /* Is the handle to a printer or to the server? */
8794 if (Printer->printer_type == SPLHND_SERVER) {
8796 union spoolss_PrinterData data;
8798 result = getprinterdata_printer_server(p->mem_ctx,
8799 r->in.value_name,
8800 r->out.type,
8801 &data);
8802 if (!W_ERROR_IS_OK(result)) {
8803 return result;
8806 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
8807 *r->out.type, &data);
8808 if (!W_ERROR_IS_OK(result)) {
8809 return result;
8812 *r->out.needed = blob.length;
8814 if (r->in.offered >= *r->out.needed) {
8815 memcpy(r->out.data, blob.data, blob.length);
8818 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8821 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8822 return WERR_BADFID;
8824 printer = lp_const_servicename(snum);
8826 /* check to see if the keyname is valid */
8827 if (!strlen(r->in.key_name)) {
8828 return WERR_INVALID_PARAM;
8831 /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
8832 if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
8833 strequal(r->in.value_name, "ChangeId")) {
8834 *r->out.type = REG_DWORD;
8835 *r->out.needed = 4;
8836 if (r->in.offered >= *r->out.needed) {
8837 uint32_t changeid = 0;
8839 result = winreg_printer_get_changeid(p->mem_ctx,
8840 p->server_info,
8841 p->msg_ctx,
8842 printer,
8843 &changeid);
8844 if (!W_ERROR_IS_OK(result)) {
8845 return result;
8848 SIVAL(r->out.data, 0, changeid);
8849 result = WERR_OK;
8851 goto done;
8854 result = winreg_get_printer_dataex(p->mem_ctx,
8855 p->server_info,
8856 p->msg_ctx,
8857 printer,
8858 r->in.key_name,
8859 r->in.value_name,
8860 &val_type,
8861 &val_data,
8862 &val_size);
8863 if (!W_ERROR_IS_OK(result)) {
8864 return result;
8867 *r->out.needed = val_size;
8868 *r->out.type = val_type;
8870 if (r->in.offered >= *r->out.needed) {
8871 memcpy(r->out.data, val_data, val_size);
8874 done:
8875 *r->out.type = SPOOLSS_BUFFER_OK(*r->out.type, REG_NONE);
8876 r->out.data = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
8878 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
8881 /****************************************************************
8882 _spoolss_SetPrinterDataEx
8883 ****************************************************************/
8885 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
8886 struct spoolss_SetPrinterDataEx *r)
8888 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
8889 int snum = 0;
8890 WERROR result = WERR_OK;
8891 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
8892 char *oid_string;
8894 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
8896 /* From MSDN documentation of SetPrinterDataEx: pass request to
8897 SetPrinterData if key is "PrinterDriverData" */
8899 if (!Printer) {
8900 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8901 OUR_HANDLE(r->in.handle)));
8902 return WERR_BADFID;
8905 if (Printer->printer_type == SPLHND_SERVER) {
8906 DEBUG(10,("_spoolss_SetPrinterDataEx: "
8907 "Not implemented for server handles yet\n"));
8908 return WERR_INVALID_PARAM;
8911 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8912 return WERR_BADFID;
8916 * Access check : NT returns "access denied" if you make a
8917 * SetPrinterData call without the necessary privildge.
8918 * we were originally returning OK if nothing changed
8919 * which made Win2k issue **a lot** of SetPrinterData
8920 * when connecting to a printer --jerry
8923 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8924 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
8925 "change denied by handle access permissions\n"));
8926 return WERR_ACCESS_DENIED;
8929 result = winreg_get_printer(Printer, p->server_info, p->msg_ctx,
8930 Printer->servername,
8931 lp_servicename(snum),
8932 &pinfo2);
8933 if (!W_ERROR_IS_OK(result)) {
8934 return result;
8937 /* check for OID in valuename */
8939 oid_string = strchr(r->in.value_name, ',');
8940 if (oid_string) {
8941 *oid_string = '\0';
8942 oid_string++;
8945 /* save the registry data */
8947 result = winreg_set_printer_dataex(p->mem_ctx,
8948 p->server_info,
8949 p->msg_ctx,
8950 pinfo2->sharename,
8951 r->in.key_name,
8952 r->in.value_name,
8953 r->in.type,
8954 r->in.data,
8955 r->in.offered);
8957 if (W_ERROR_IS_OK(result)) {
8958 /* save the OID if one was specified */
8959 if (oid_string) {
8960 char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
8961 r->in.key_name, SPOOL_OID_KEY);
8962 if (!str) {
8963 result = WERR_NOMEM;
8964 goto done;
8968 * I'm not checking the status here on purpose. Don't know
8969 * if this is right, but I'm returning the status from the
8970 * previous set_printer_dataex() call. I have no idea if
8971 * this is right. --jerry
8973 winreg_set_printer_dataex(p->mem_ctx,
8974 p->server_info,
8975 p->msg_ctx,
8976 pinfo2->sharename,
8977 str,
8978 r->in.value_name,
8979 REG_SZ,
8980 (uint8_t *) oid_string,
8981 strlen(oid_string) + 1);
8984 result = winreg_printer_update_changeid(p->mem_ctx,
8985 p->server_info,
8986 p->msg_ctx,
8987 lp_const_servicename(snum));
8991 done:
8992 talloc_free(pinfo2);
8993 return result;
8996 /****************************************************************
8997 _spoolss_DeletePrinterDataEx
8998 ****************************************************************/
9000 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9001 struct spoolss_DeletePrinterDataEx *r)
9003 const char *printer;
9004 int snum=0;
9005 WERROR status = WERR_OK;
9006 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9008 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9010 if (!Printer) {
9011 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9012 "Invalid handle (%s:%u:%u).\n",
9013 OUR_HANDLE(r->in.handle)));
9014 return WERR_BADFID;
9017 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9018 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9019 "printer properties change denied by handle\n"));
9020 return WERR_ACCESS_DENIED;
9023 if (!r->in.value_name || !r->in.key_name) {
9024 return WERR_NOMEM;
9027 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9028 return WERR_BADFID;
9030 printer = lp_const_servicename(snum);
9032 status = winreg_delete_printer_dataex(p->mem_ctx,
9033 p->server_info,
9034 p->msg_ctx,
9035 printer,
9036 r->in.key_name,
9037 r->in.value_name);
9038 if (W_ERROR_IS_OK(status)) {
9039 status = winreg_printer_update_changeid(p->mem_ctx,
9040 p->server_info,
9041 p->msg_ctx,
9042 printer);
9045 return status;
9048 /****************************************************************
9049 _spoolss_EnumPrinterKey
9050 ****************************************************************/
9052 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9053 struct spoolss_EnumPrinterKey *r)
9055 uint32_t num_keys;
9056 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9057 int snum = 0;
9058 WERROR result = WERR_BADFILE;
9059 const char **array = NULL;
9060 DATA_BLOB blob;
9062 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9064 if (!Printer) {
9065 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9066 OUR_HANDLE(r->in.handle)));
9067 return WERR_BADFID;
9070 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9071 return WERR_BADFID;
9074 result = winreg_enum_printer_key(p->mem_ctx,
9075 p->server_info,
9076 p->msg_ctx,
9077 lp_const_servicename(snum),
9078 r->in.key_name,
9079 &num_keys,
9080 &array);
9081 if (!W_ERROR_IS_OK(result)) {
9082 goto done;
9085 if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9086 result = WERR_NOMEM;
9087 goto done;
9090 *r->out._ndr_size = r->in.offered / 2;
9091 *r->out.needed = blob.length;
9093 if (r->in.offered < *r->out.needed) {
9094 result = WERR_MORE_DATA;
9095 } else {
9096 result = WERR_OK;
9097 r->out.key_buffer->string_array = array;
9100 done:
9101 if (!W_ERROR_IS_OK(result)) {
9102 TALLOC_FREE(array);
9103 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9104 *r->out.needed = 0;
9108 return result;
9111 /****************************************************************
9112 _spoolss_DeletePrinterKey
9113 ****************************************************************/
9115 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9116 struct spoolss_DeletePrinterKey *r)
9118 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9119 int snum=0;
9120 WERROR status;
9121 const char *printer;
9123 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9125 if (!Printer) {
9126 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9127 OUR_HANDLE(r->in.handle)));
9128 return WERR_BADFID;
9131 /* if keyname == NULL, return error */
9132 if ( !r->in.key_name )
9133 return WERR_INVALID_PARAM;
9135 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9136 return WERR_BADFID;
9139 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9140 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9141 "printer properties change denied by handle\n"));
9142 return WERR_ACCESS_DENIED;
9145 printer = lp_const_servicename(snum);
9147 /* delete the key and all subkeys */
9148 status = winreg_delete_printer_key(p->mem_ctx,
9149 p->server_info,
9150 p->msg_ctx,
9151 printer,
9152 r->in.key_name);
9153 if (W_ERROR_IS_OK(status)) {
9154 status = winreg_printer_update_changeid(p->mem_ctx,
9155 p->server_info,
9156 p->msg_ctx,
9157 printer);
9160 return status;
9163 /****************************************************************
9164 _spoolss_EnumPrinterDataEx
9165 ****************************************************************/
9167 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
9168 struct spoolss_EnumPrinterDataEx *r)
9170 uint32_t count = 0;
9171 struct spoolss_PrinterEnumValues *info = NULL;
9172 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9173 int snum;
9174 WERROR result;
9176 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9178 *r->out.count = 0;
9179 *r->out.needed = 0;
9180 *r->out.info = NULL;
9182 if (!Printer) {
9183 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9184 OUR_HANDLE(r->in.handle)));
9185 return WERR_BADFID;
9189 * first check for a keyname of NULL or "". Win2k seems to send
9190 * this a lot and we should send back WERR_INVALID_PARAM
9191 * no need to spend time looking up the printer in this case.
9192 * --jerry
9195 if (!strlen(r->in.key_name)) {
9196 result = WERR_INVALID_PARAM;
9197 goto done;
9200 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9201 return WERR_BADFID;
9204 /* now look for a match on the key name */
9205 result = winreg_enum_printer_dataex(p->mem_ctx,
9206 p->server_info,
9207 p->msg_ctx,
9208 lp_const_servicename(snum),
9209 r->in.key_name,
9210 &count,
9211 &info);
9212 if (!W_ERROR_IS_OK(result)) {
9213 goto done;
9216 #if 0 /* FIXME - gd */
9217 /* housekeeping information in the reply */
9219 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9220 * the hand marshalled container size is a multiple
9221 * of 4 bytes for RPC alignment.
9224 if (needed % 4) {
9225 needed += 4-(needed % 4);
9227 #endif
9228 *r->out.count = count;
9229 *r->out.info = info;
9231 done:
9232 if (!W_ERROR_IS_OK(result)) {
9233 return result;
9236 *r->out.needed = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9237 spoolss_EnumPrinterDataEx,
9238 *r->out.info,
9239 *r->out.count);
9240 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9241 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9243 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9246 /****************************************************************************
9247 ****************************************************************************/
9249 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9250 const char *servername,
9251 const char *environment,
9252 struct spoolss_PrintProcessorDirectoryInfo1 *r)
9254 WERROR werr;
9255 char *path = NULL;
9257 werr = compose_spoolss_server_path(mem_ctx,
9258 servername,
9259 environment,
9260 SPOOLSS_PRTPROCS_PATH,
9261 &path);
9262 if (!W_ERROR_IS_OK(werr)) {
9263 return werr;
9266 DEBUG(4,("print processor directory: [%s]\n", path));
9268 r->directory_name = path;
9270 return WERR_OK;
9273 /****************************************************************
9274 _spoolss_GetPrintProcessorDirectory
9275 ****************************************************************/
9277 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
9278 struct spoolss_GetPrintProcessorDirectory *r)
9280 WERROR result;
9282 /* that's an [in out] buffer */
9284 if (!r->in.buffer && (r->in.offered != 0)) {
9285 return WERR_INVALID_PARAM;
9288 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9289 r->in.level));
9291 *r->out.needed = 0;
9293 /* r->in.level is ignored */
9295 /* We always should reply with a local print processor directory so that
9296 * users are not forced to have a [prnproc$] share on the Samba spoolss
9297 * server - Guenther */
9299 result = getprintprocessordirectory_level_1(p->mem_ctx,
9300 NULL, /* r->in.server */
9301 r->in.environment,
9302 &r->out.info->info1);
9303 if (!W_ERROR_IS_OK(result)) {
9304 TALLOC_FREE(r->out.info);
9305 return result;
9308 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
9309 r->out.info, r->in.level);
9310 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9312 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9315 /*******************************************************************
9316 ********************************************************************/
9318 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9319 const char *dllname)
9321 enum ndr_err_code ndr_err;
9322 struct spoolss_MonitorUi ui;
9324 ui.dll_name = dllname;
9326 ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
9327 (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9328 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9329 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9331 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9334 /*******************************************************************
9335 Streams the monitor UI DLL name in UNICODE
9336 *******************************************************************/
9338 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9339 NT_USER_TOKEN *token, DATA_BLOB *in,
9340 DATA_BLOB *out, uint32_t *needed)
9342 const char *dllname = "tcpmonui.dll";
9344 *needed = (strlen(dllname)+1) * 2;
9346 if (out->length < *needed) {
9347 return WERR_INSUFFICIENT_BUFFER;
9350 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9351 return WERR_NOMEM;
9354 return WERR_OK;
9357 /*******************************************************************
9358 ********************************************************************/
9360 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9361 struct spoolss_PortData1 *port1,
9362 const DATA_BLOB *buf)
9364 enum ndr_err_code ndr_err;
9365 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
9366 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9367 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9368 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9370 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9373 /*******************************************************************
9374 ********************************************************************/
9376 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9377 struct spoolss_PortData2 *port2,
9378 const DATA_BLOB *buf)
9380 enum ndr_err_code ndr_err;
9381 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
9382 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9383 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9384 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9386 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9389 /*******************************************************************
9390 Create a new TCP/IP port
9391 *******************************************************************/
9393 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9394 NT_USER_TOKEN *token, DATA_BLOB *in,
9395 DATA_BLOB *out, uint32_t *needed)
9397 struct spoolss_PortData1 port1;
9398 struct spoolss_PortData2 port2;
9399 char *device_uri = NULL;
9400 uint32_t version;
9402 const char *portname;
9403 const char *hostaddress;
9404 const char *queue;
9405 uint32_t port_number;
9406 uint32_t protocol;
9408 /* peek for spoolss_PortData version */
9410 if (!in || (in->length < (128 + 4))) {
9411 return WERR_GENERAL_FAILURE;
9414 version = IVAL(in->data, 128);
9416 switch (version) {
9417 case 1:
9418 ZERO_STRUCT(port1);
9420 if (!pull_port_data_1(mem_ctx, &port1, in)) {
9421 return WERR_NOMEM;
9424 portname = port1.portname;
9425 hostaddress = port1.hostaddress;
9426 queue = port1.queue;
9427 protocol = port1.protocol;
9428 port_number = port1.port_number;
9430 break;
9431 case 2:
9432 ZERO_STRUCT(port2);
9434 if (!pull_port_data_2(mem_ctx, &port2, in)) {
9435 return WERR_NOMEM;
9438 portname = port2.portname;
9439 hostaddress = port2.hostaddress;
9440 queue = port2.queue;
9441 protocol = port2.protocol;
9442 port_number = port2.port_number;
9444 break;
9445 default:
9446 DEBUG(1,("xcvtcp_addport: "
9447 "unknown version of port_data: %d\n", version));
9448 return WERR_UNKNOWN_PORT;
9451 /* create the device URI and call the add_port_hook() */
9453 switch (protocol) {
9454 case PROTOCOL_RAWTCP_TYPE:
9455 device_uri = talloc_asprintf(mem_ctx,
9456 "socket://%s:%d/", hostaddress,
9457 port_number);
9458 break;
9460 case PROTOCOL_LPR_TYPE:
9461 device_uri = talloc_asprintf(mem_ctx,
9462 "lpr://%s/%s", hostaddress, queue );
9463 break;
9465 default:
9466 return WERR_UNKNOWN_PORT;
9469 if (!device_uri) {
9470 return WERR_NOMEM;
9473 return add_port_hook(mem_ctx, token, portname, device_uri);
9476 /*******************************************************************
9477 *******************************************************************/
9479 struct xcv_api_table xcvtcp_cmds[] = {
9480 { "MonitorUI", xcvtcp_monitorui },
9481 { "AddPort", xcvtcp_addport},
9482 { NULL, NULL }
9485 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9486 NT_USER_TOKEN *token, const char *command,
9487 DATA_BLOB *inbuf,
9488 DATA_BLOB *outbuf,
9489 uint32_t *needed )
9491 int i;
9493 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9495 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9496 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9497 return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9500 return WERR_BADFUNC;
9503 /*******************************************************************
9504 *******************************************************************/
9505 #if 0 /* don't support management using the "Local Port" monitor */
9507 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9508 NT_USER_TOKEN *token, DATA_BLOB *in,
9509 DATA_BLOB *out, uint32_t *needed)
9511 const char *dllname = "localui.dll";
9513 *needed = (strlen(dllname)+1) * 2;
9515 if (out->length < *needed) {
9516 return WERR_INSUFFICIENT_BUFFER;
9519 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9520 return WERR_NOMEM;
9523 return WERR_OK;
9526 /*******************************************************************
9527 *******************************************************************/
9529 struct xcv_api_table xcvlocal_cmds[] = {
9530 { "MonitorUI", xcvlocal_monitorui },
9531 { NULL, NULL }
9533 #else
9534 struct xcv_api_table xcvlocal_cmds[] = {
9535 { NULL, NULL }
9537 #endif
9541 /*******************************************************************
9542 *******************************************************************/
9544 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9545 NT_USER_TOKEN *token, const char *command,
9546 DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9547 uint32_t *needed)
9549 int i;
9551 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9553 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9554 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9555 return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9557 return WERR_BADFUNC;
9560 /****************************************************************
9561 _spoolss_XcvData
9562 ****************************************************************/
9564 WERROR _spoolss_XcvData(struct pipes_struct *p,
9565 struct spoolss_XcvData *r)
9567 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
9568 DATA_BLOB out_data = data_blob_null;
9569 WERROR werror;
9571 if (!Printer) {
9572 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9573 OUR_HANDLE(r->in.handle)));
9574 return WERR_BADFID;
9577 /* Has to be a handle to the TCP/IP port monitor */
9579 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9580 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9581 return WERR_BADFID;
9584 /* requires administrative access to the server */
9586 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9587 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9588 return WERR_ACCESS_DENIED;
9591 /* Allocate the outgoing buffer */
9593 if (r->in.out_data_size) {
9594 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9595 if (out_data.data == NULL) {
9596 return WERR_NOMEM;
9600 switch ( Printer->printer_type ) {
9601 case SPLHND_PORTMON_TCP:
9602 werror = process_xcvtcp_command(p->mem_ctx,
9603 p->server_info->ptok,
9604 r->in.function_name,
9605 &r->in.in_data, &out_data,
9606 r->out.needed);
9607 break;
9608 case SPLHND_PORTMON_LOCAL:
9609 werror = process_xcvlocal_command(p->mem_ctx,
9610 p->server_info->ptok,
9611 r->in.function_name,
9612 &r->in.in_data, &out_data,
9613 r->out.needed);
9614 break;
9615 default:
9616 werror = WERR_INVALID_PRINT_MONITOR;
9619 if (!W_ERROR_IS_OK(werror)) {
9620 return werror;
9623 *r->out.status_code = 0;
9625 if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
9626 memcpy(r->out.out_data, out_data.data,
9627 MIN(r->in.out_data_size, out_data.length));
9630 return WERR_OK;
9633 /****************************************************************
9634 _spoolss_AddPrintProcessor
9635 ****************************************************************/
9637 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
9638 struct spoolss_AddPrintProcessor *r)
9640 /* for now, just indicate success and ignore the add. We'll
9641 automatically set the winprint processor for printer
9642 entries later. Used to debug the LexMark Optra S 1855 PCL
9643 driver --jerry */
9645 return WERR_OK;
9648 /****************************************************************
9649 _spoolss_AddPort
9650 ****************************************************************/
9652 WERROR _spoolss_AddPort(struct pipes_struct *p,
9653 struct spoolss_AddPort *r)
9655 /* do what w2k3 does */
9657 return WERR_NOT_SUPPORTED;
9660 /****************************************************************
9661 _spoolss_GetPrinterDriver
9662 ****************************************************************/
9664 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
9665 struct spoolss_GetPrinterDriver *r)
9667 p->rng_fault_state = true;
9668 return WERR_NOT_SUPPORTED;
9671 /****************************************************************
9672 _spoolss_ReadPrinter
9673 ****************************************************************/
9675 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
9676 struct spoolss_ReadPrinter *r)
9678 p->rng_fault_state = true;
9679 return WERR_NOT_SUPPORTED;
9682 /****************************************************************
9683 _spoolss_WaitForPrinterChange
9684 ****************************************************************/
9686 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
9687 struct spoolss_WaitForPrinterChange *r)
9689 p->rng_fault_state = true;
9690 return WERR_NOT_SUPPORTED;
9693 /****************************************************************
9694 _spoolss_ConfigurePort
9695 ****************************************************************/
9697 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
9698 struct spoolss_ConfigurePort *r)
9700 p->rng_fault_state = true;
9701 return WERR_NOT_SUPPORTED;
9704 /****************************************************************
9705 _spoolss_DeletePort
9706 ****************************************************************/
9708 WERROR _spoolss_DeletePort(struct pipes_struct *p,
9709 struct spoolss_DeletePort *r)
9711 p->rng_fault_state = true;
9712 return WERR_NOT_SUPPORTED;
9715 /****************************************************************
9716 _spoolss_CreatePrinterIC
9717 ****************************************************************/
9719 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
9720 struct spoolss_CreatePrinterIC *r)
9722 p->rng_fault_state = true;
9723 return WERR_NOT_SUPPORTED;
9726 /****************************************************************
9727 _spoolss_PlayGDIScriptOnPrinterIC
9728 ****************************************************************/
9730 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
9731 struct spoolss_PlayGDIScriptOnPrinterIC *r)
9733 p->rng_fault_state = true;
9734 return WERR_NOT_SUPPORTED;
9737 /****************************************************************
9738 _spoolss_DeletePrinterIC
9739 ****************************************************************/
9741 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
9742 struct spoolss_DeletePrinterIC *r)
9744 p->rng_fault_state = true;
9745 return WERR_NOT_SUPPORTED;
9748 /****************************************************************
9749 _spoolss_AddPrinterConnection
9750 ****************************************************************/
9752 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
9753 struct spoolss_AddPrinterConnection *r)
9755 p->rng_fault_state = true;
9756 return WERR_NOT_SUPPORTED;
9759 /****************************************************************
9760 _spoolss_DeletePrinterConnection
9761 ****************************************************************/
9763 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
9764 struct spoolss_DeletePrinterConnection *r)
9766 p->rng_fault_state = true;
9767 return WERR_NOT_SUPPORTED;
9770 /****************************************************************
9771 _spoolss_PrinterMessageBox
9772 ****************************************************************/
9774 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
9775 struct spoolss_PrinterMessageBox *r)
9777 p->rng_fault_state = true;
9778 return WERR_NOT_SUPPORTED;
9781 /****************************************************************
9782 _spoolss_AddMonitor
9783 ****************************************************************/
9785 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
9786 struct spoolss_AddMonitor *r)
9788 p->rng_fault_state = true;
9789 return WERR_NOT_SUPPORTED;
9792 /****************************************************************
9793 _spoolss_DeleteMonitor
9794 ****************************************************************/
9796 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
9797 struct spoolss_DeleteMonitor *r)
9799 p->rng_fault_state = true;
9800 return WERR_NOT_SUPPORTED;
9803 /****************************************************************
9804 _spoolss_DeletePrintProcessor
9805 ****************************************************************/
9807 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
9808 struct spoolss_DeletePrintProcessor *r)
9810 p->rng_fault_state = true;
9811 return WERR_NOT_SUPPORTED;
9814 /****************************************************************
9815 _spoolss_AddPrintProvidor
9816 ****************************************************************/
9818 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
9819 struct spoolss_AddPrintProvidor *r)
9821 p->rng_fault_state = true;
9822 return WERR_NOT_SUPPORTED;
9825 /****************************************************************
9826 _spoolss_DeletePrintProvidor
9827 ****************************************************************/
9829 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
9830 struct spoolss_DeletePrintProvidor *r)
9832 p->rng_fault_state = true;
9833 return WERR_NOT_SUPPORTED;
9836 /****************************************************************
9837 _spoolss_FindFirstPrinterChangeNotification
9838 ****************************************************************/
9840 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
9841 struct spoolss_FindFirstPrinterChangeNotification *r)
9843 p->rng_fault_state = true;
9844 return WERR_NOT_SUPPORTED;
9847 /****************************************************************
9848 _spoolss_FindNextPrinterChangeNotification
9849 ****************************************************************/
9851 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
9852 struct spoolss_FindNextPrinterChangeNotification *r)
9854 p->rng_fault_state = true;
9855 return WERR_NOT_SUPPORTED;
9858 /****************************************************************
9859 _spoolss_RouterFindFirstPrinterChangeNotificationOld
9860 ****************************************************************/
9862 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
9863 struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
9865 p->rng_fault_state = true;
9866 return WERR_NOT_SUPPORTED;
9869 /****************************************************************
9870 _spoolss_ReplyOpenPrinter
9871 ****************************************************************/
9873 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
9874 struct spoolss_ReplyOpenPrinter *r)
9876 p->rng_fault_state = true;
9877 return WERR_NOT_SUPPORTED;
9880 /****************************************************************
9881 _spoolss_RouterReplyPrinter
9882 ****************************************************************/
9884 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
9885 struct spoolss_RouterReplyPrinter *r)
9887 p->rng_fault_state = true;
9888 return WERR_NOT_SUPPORTED;
9891 /****************************************************************
9892 _spoolss_ReplyClosePrinter
9893 ****************************************************************/
9895 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
9896 struct spoolss_ReplyClosePrinter *r)
9898 p->rng_fault_state = true;
9899 return WERR_NOT_SUPPORTED;
9902 /****************************************************************
9903 _spoolss_AddPortEx
9904 ****************************************************************/
9906 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
9907 struct spoolss_AddPortEx *r)
9909 p->rng_fault_state = true;
9910 return WERR_NOT_SUPPORTED;
9913 /****************************************************************
9914 _spoolss_RouterFindFirstPrinterChangeNotification
9915 ****************************************************************/
9917 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
9918 struct spoolss_RouterFindFirstPrinterChangeNotification *r)
9920 p->rng_fault_state = true;
9921 return WERR_NOT_SUPPORTED;
9924 /****************************************************************
9925 _spoolss_SpoolerInit
9926 ****************************************************************/
9928 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
9929 struct spoolss_SpoolerInit *r)
9931 p->rng_fault_state = true;
9932 return WERR_NOT_SUPPORTED;
9935 /****************************************************************
9936 _spoolss_ResetPrinterEx
9937 ****************************************************************/
9939 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
9940 struct spoolss_ResetPrinterEx *r)
9942 p->rng_fault_state = true;
9943 return WERR_NOT_SUPPORTED;
9946 /****************************************************************
9947 _spoolss_RouterReplyPrinterEx
9948 ****************************************************************/
9950 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
9951 struct spoolss_RouterReplyPrinterEx *r)
9953 p->rng_fault_state = true;
9954 return WERR_NOT_SUPPORTED;
9957 /****************************************************************
9958 _spoolss_44
9959 ****************************************************************/
9961 WERROR _spoolss_44(struct pipes_struct *p,
9962 struct spoolss_44 *r)
9964 p->rng_fault_state = true;
9965 return WERR_NOT_SUPPORTED;
9968 /****************************************************************
9969 _spoolss_47
9970 ****************************************************************/
9972 WERROR _spoolss_47(struct pipes_struct *p,
9973 struct spoolss_47 *r)
9975 p->rng_fault_state = true;
9976 return WERR_NOT_SUPPORTED;
9979 /****************************************************************
9980 _spoolss_4a
9981 ****************************************************************/
9983 WERROR _spoolss_4a(struct pipes_struct *p,
9984 struct spoolss_4a *r)
9986 p->rng_fault_state = true;
9987 return WERR_NOT_SUPPORTED;
9990 /****************************************************************
9991 _spoolss_4b
9992 ****************************************************************/
9994 WERROR _spoolss_4b(struct pipes_struct *p,
9995 struct spoolss_4b *r)
9997 p->rng_fault_state = true;
9998 return WERR_NOT_SUPPORTED;
10001 /****************************************************************
10002 _spoolss_4c
10003 ****************************************************************/
10005 WERROR _spoolss_4c(struct pipes_struct *p,
10006 struct spoolss_4c *r)
10008 p->rng_fault_state = true;
10009 return WERR_NOT_SUPPORTED;
10012 /****************************************************************
10013 _spoolss_53
10014 ****************************************************************/
10016 WERROR _spoolss_53(struct pipes_struct *p,
10017 struct spoolss_53 *r)
10019 p->rng_fault_state = true;
10020 return WERR_NOT_SUPPORTED;
10023 /****************************************************************
10024 _spoolss_55
10025 ****************************************************************/
10027 WERROR _spoolss_55(struct pipes_struct *p,
10028 struct spoolss_55 *r)
10030 p->rng_fault_state = true;
10031 return WERR_NOT_SUPPORTED;
10034 /****************************************************************
10035 _spoolss_56
10036 ****************************************************************/
10038 WERROR _spoolss_56(struct pipes_struct *p,
10039 struct spoolss_56 *r)
10041 p->rng_fault_state = true;
10042 return WERR_NOT_SUPPORTED;
10045 /****************************************************************
10046 _spoolss_57
10047 ****************************************************************/
10049 WERROR _spoolss_57(struct pipes_struct *p,
10050 struct spoolss_57 *r)
10052 p->rng_fault_state = true;
10053 return WERR_NOT_SUPPORTED;
10056 /****************************************************************
10057 _spoolss_5a
10058 ****************************************************************/
10060 WERROR _spoolss_5a(struct pipes_struct *p,
10061 struct spoolss_5a *r)
10063 p->rng_fault_state = true;
10064 return WERR_NOT_SUPPORTED;
10067 /****************************************************************
10068 _spoolss_5b
10069 ****************************************************************/
10071 WERROR _spoolss_5b(struct pipes_struct *p,
10072 struct spoolss_5b *r)
10074 p->rng_fault_state = true;
10075 return WERR_NOT_SUPPORTED;
10078 /****************************************************************
10079 _spoolss_5c
10080 ****************************************************************/
10082 WERROR _spoolss_5c(struct pipes_struct *p,
10083 struct spoolss_5c *r)
10085 p->rng_fault_state = true;
10086 return WERR_NOT_SUPPORTED;
10089 /****************************************************************
10090 _spoolss_5d
10091 ****************************************************************/
10093 WERROR _spoolss_5d(struct pipes_struct *p,
10094 struct spoolss_5d *r)
10096 p->rng_fault_state = true;
10097 return WERR_NOT_SUPPORTED;
10100 /****************************************************************
10101 _spoolss_5e
10102 ****************************************************************/
10104 WERROR _spoolss_5e(struct pipes_struct *p,
10105 struct spoolss_5e *r)
10107 p->rng_fault_state = true;
10108 return WERR_NOT_SUPPORTED;
10111 /****************************************************************
10112 _spoolss_5f
10113 ****************************************************************/
10115 WERROR _spoolss_5f(struct pipes_struct *p,
10116 struct spoolss_5f *r)
10118 p->rng_fault_state = true;
10119 return WERR_NOT_SUPPORTED;
10122 /****************************************************************
10123 _spoolss_60
10124 ****************************************************************/
10126 WERROR _spoolss_60(struct pipes_struct *p,
10127 struct spoolss_60 *r)
10129 p->rng_fault_state = true;
10130 return WERR_NOT_SUPPORTED;
10133 /****************************************************************
10134 _spoolss_61
10135 ****************************************************************/
10137 WERROR _spoolss_61(struct pipes_struct *p,
10138 struct spoolss_61 *r)
10140 p->rng_fault_state = true;
10141 return WERR_NOT_SUPPORTED;
10144 /****************************************************************
10145 _spoolss_62
10146 ****************************************************************/
10148 WERROR _spoolss_62(struct pipes_struct *p,
10149 struct spoolss_62 *r)
10151 p->rng_fault_state = true;
10152 return WERR_NOT_SUPPORTED;
10155 /****************************************************************
10156 _spoolss_63
10157 ****************************************************************/
10159 WERROR _spoolss_63(struct pipes_struct *p,
10160 struct spoolss_63 *r)
10162 p->rng_fault_state = true;
10163 return WERR_NOT_SUPPORTED;
10166 /****************************************************************
10167 _spoolss_64
10168 ****************************************************************/
10170 WERROR _spoolss_64(struct pipes_struct *p,
10171 struct spoolss_64 *r)
10173 p->rng_fault_state = true;
10174 return WERR_NOT_SUPPORTED;
10177 /****************************************************************
10178 _spoolss_65
10179 ****************************************************************/
10181 WERROR _spoolss_65(struct pipes_struct *p,
10182 struct spoolss_65 *r)
10184 p->rng_fault_state = true;
10185 return WERR_NOT_SUPPORTED;
10188 /****************************************************************
10189 _spoolss_GetCorePrinterDrivers
10190 ****************************************************************/
10192 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
10193 struct spoolss_GetCorePrinterDrivers *r)
10195 p->rng_fault_state = true;
10196 return WERR_NOT_SUPPORTED;
10199 /****************************************************************
10200 _spoolss_67
10201 ****************************************************************/
10203 WERROR _spoolss_67(struct pipes_struct *p,
10204 struct spoolss_67 *r)
10206 p->rng_fault_state = true;
10207 return WERR_NOT_SUPPORTED;
10210 /****************************************************************
10211 _spoolss_GetPrinterDriverPackagePath
10212 ****************************************************************/
10214 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
10215 struct spoolss_GetPrinterDriverPackagePath *r)
10217 p->rng_fault_state = true;
10218 return WERR_NOT_SUPPORTED;
10221 /****************************************************************
10222 _spoolss_69
10223 ****************************************************************/
10225 WERROR _spoolss_69(struct pipes_struct *p,
10226 struct spoolss_69 *r)
10228 p->rng_fault_state = true;
10229 return WERR_NOT_SUPPORTED;
10232 /****************************************************************
10233 _spoolss_6a
10234 ****************************************************************/
10236 WERROR _spoolss_6a(struct pipes_struct *p,
10237 struct spoolss_6a *r)
10239 p->rng_fault_state = true;
10240 return WERR_NOT_SUPPORTED;
10243 /****************************************************************
10244 _spoolss_6b
10245 ****************************************************************/
10247 WERROR _spoolss_6b(struct pipes_struct *p,
10248 struct spoolss_6b *r)
10250 p->rng_fault_state = true;
10251 return WERR_NOT_SUPPORTED;
10254 /****************************************************************
10255 _spoolss_6c
10256 ****************************************************************/
10258 WERROR _spoolss_6c(struct pipes_struct *p,
10259 struct spoolss_6c *r)
10261 p->rng_fault_state = true;
10262 return WERR_NOT_SUPPORTED;
10265 /****************************************************************
10266 _spoolss_6d
10267 ****************************************************************/
10269 WERROR _spoolss_6d(struct pipes_struct *p,
10270 struct spoolss_6d *r)
10272 p->rng_fault_state = true;
10273 return WERR_NOT_SUPPORTED;