s3-spoolss: Use get_session_info_system().
[metze/samba/wip.git] / source3 / rpc_server / spoolss / srv_spoolss_nt.c
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.
12  *
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.
17  *
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.
22  *
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/>.
25  */
26
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. */
29
30 #include "includes.h"
31 #include "ntdomain.h"
32 #include "nt_printing.h"
33 #include "srv_spoolss_util.h"
34 #include "../librpc/gen_ndr/srv_spoolss.h"
35 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
36 #include "rpc_client/init_spoolss.h"
37 #include "rpc_client/cli_pipe.h"
38 #include "../libcli/security/security.h"
39 #include "librpc/gen_ndr/ndr_security.h"
40 #include "registry.h"
41 #include "registry/reg_objects.h"
42 #include "include/printing.h"
43 #include "secrets.h"
44 #include "../librpc/gen_ndr/netlogon.h"
45 #include "rpc_misc.h"
46 #include "printing/notify.h"
47 #include "serverid.h"
48 #include "../libcli/registry/util_reg.h"
49 #include "smbd/smbd.h"
50 #include "smbd/globals.h"
51 #include "auth.h"
52 #include "messages.h"
53 #include "rpc_server/spoolss/srv_spoolss_nt.h"
54 #include "util_tdb.h"
55 #include "libsmb/libsmb.h"
56 #include "printing/printer_list.h"
57 #include "../lib/tsocket/tsocket.h"
58 #include "rpc_client/cli_winreg_spoolss.h"
59
60 /* macros stolen from s4 spoolss server */
61 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
62         ((info)?ndr_size_##fn(info, level, 0):0)
63
64 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
65         ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
66
67 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
68         ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
69
70 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
71
72 #undef DBGC_CLASS
73 #define DBGC_CLASS DBGC_RPC_SRV
74
75 #ifndef MAX_OPEN_PRINTER_EXS
76 #define MAX_OPEN_PRINTER_EXS 50
77 #endif
78
79 struct notify_back_channel;
80
81 /* structure to store the printer handles */
82 /* and a reference to what it's pointing to */
83 /* and the notify info asked about */
84 /* that's the central struct */
85 struct printer_handle {
86         struct printer_handle *prev, *next;
87         bool document_started;
88         bool page_started;
89         uint32 jobid; /* jobid in printing backend */
90         int printer_type;
91         const char *servername;
92         fstring sharename;
93         uint32 type;
94         uint32 access_granted;
95         struct {
96                 uint32 flags;
97                 uint32 options;
98                 fstring localmachine;
99                 uint32 printerlocal;
100                 struct spoolss_NotifyOption *option;
101                 struct policy_handle cli_hnd;
102                 struct notify_back_channel *cli_chan;
103                 uint32 change;
104                 /* are we in a FindNextPrinterChangeNotify() call? */
105                 bool fnpcn;
106                 struct messaging_context *msg_ctx;
107         } notify;
108         struct {
109                 fstring machine;
110                 fstring user;
111         } client;
112
113         /* devmode sent in the OpenPrinter() call */
114         struct spoolss_DeviceMode *devmode;
115
116         /* TODO cache the printer info2 structure */
117         struct spoolss_PrinterInfo2 *info2;
118
119 };
120
121 static struct printer_handle *printers_list;
122
123 struct printer_session_counter {
124         struct printer_session_counter *next;
125         struct printer_session_counter *prev;
126
127         int snum;
128         uint32_t counter;
129 };
130
131 static struct printer_session_counter *counter_list;
132
133 struct notify_back_channel {
134         struct notify_back_channel *prev, *next;
135
136         /* associated client */
137         struct sockaddr_storage client_address;
138
139         /* print notify back-channel pipe handle*/
140         struct rpc_pipe_client *cli_pipe;
141         struct dcerpc_binding_handle *binding_handle;
142         uint32_t active_connections;
143 };
144
145 static struct notify_back_channel *back_channels;
146
147 /* Map generic permissions to printer object specific permissions */
148
149 const struct standard_mapping printer_std_mapping = {
150         PRINTER_READ,
151         PRINTER_WRITE,
152         PRINTER_EXECUTE,
153         PRINTER_ALL_ACCESS
154 };
155
156 /* Map generic permissions to print server object specific permissions */
157
158 const struct standard_mapping printserver_std_mapping = {
159         SERVER_READ,
160         SERVER_WRITE,
161         SERVER_EXECUTE,
162         SERVER_ALL_ACCESS
163 };
164
165 /* API table for Xcv Monitor functions */
166
167 struct xcv_api_table {
168         const char *name;
169         WERROR(*fn) (TALLOC_CTX *mem_ctx, struct security_token *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
170 };
171
172 static void prune_printername_cache(void);
173
174 /********************************************************************
175  * Canonicalize servername.
176  ********************************************************************/
177
178 static const char *canon_servername(const char *servername)
179 {
180         const char *pservername = servername;
181         while (*pservername == '\\') {
182                 pservername++;
183         }
184         return pservername;
185 }
186
187 /* translate between internal status numbers and NT status numbers */
188 static int nt_printj_status(int v)
189 {
190         switch (v) {
191         case LPQ_QUEUED:
192                 return 0;
193         case LPQ_PAUSED:
194                 return JOB_STATUS_PAUSED;
195         case LPQ_SPOOLING:
196                 return JOB_STATUS_SPOOLING;
197         case LPQ_PRINTING:
198                 return JOB_STATUS_PRINTING;
199         case LPQ_ERROR:
200                 return JOB_STATUS_ERROR;
201         case LPQ_DELETING:
202                 return JOB_STATUS_DELETING;
203         case LPQ_OFFLINE:
204                 return JOB_STATUS_OFFLINE;
205         case LPQ_PAPEROUT:
206                 return JOB_STATUS_PAPEROUT;
207         case LPQ_PRINTED:
208                 return JOB_STATUS_PRINTED;
209         case LPQ_DELETED:
210                 return JOB_STATUS_DELETED;
211         case LPQ_BLOCKED:
212                 return JOB_STATUS_BLOCKED_DEVQ;
213         case LPQ_USER_INTERVENTION:
214                 return JOB_STATUS_USER_INTERVENTION;
215         }
216         return 0;
217 }
218
219 static int nt_printq_status(int v)
220 {
221         switch (v) {
222         case LPQ_PAUSED:
223                 return PRINTER_STATUS_PAUSED;
224         case LPQ_QUEUED:
225         case LPQ_SPOOLING:
226         case LPQ_PRINTING:
227                 return 0;
228         }
229         return 0;
230 }
231
232 /***************************************************************************
233  Disconnect from the client
234 ****************************************************************************/
235
236 static void srv_spoolss_replycloseprinter(int snum,
237                                           struct printer_handle *prn_hnd)
238 {
239         WERROR result;
240         NTSTATUS status;
241
242         /*
243          * Tell the specific printing tdb we no longer want messages for this printer
244          * by deregistering our PID.
245          */
246
247         if (!print_notify_deregister_pid(snum)) {
248                 DEBUG(0, ("Failed to register our pid for printer %s\n",
249                           lp_const_servicename(snum)));
250         }
251
252         /* weird if the test succeeds !!! */
253         if (prn_hnd->notify.cli_chan == NULL ||
254             prn_hnd->notify.cli_chan->active_connections == 0) {
255                 DEBUG(0, ("Trying to close unexisting backchannel!\n"));
256                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
257                 TALLOC_FREE(prn_hnd->notify.cli_chan);
258                 return;
259         }
260
261         status = dcerpc_spoolss_ReplyClosePrinter(
262                                         prn_hnd->notify.cli_chan->binding_handle,
263                                         talloc_tos(),
264                                         &prn_hnd->notify.cli_hnd,
265                                         &result);
266         if (!NT_STATUS_IS_OK(status)) {
267                 DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
268                           nt_errstr(status)));
269                 result = ntstatus_to_werror(status);
270         } else if (!W_ERROR_IS_OK(result)) {
271                 DEBUG(0, ("reply_close_printer failed [%s].\n",
272                           win_errstr(result)));
273         }
274
275         /* if it's the last connection, deconnect the IPC$ share */
276         if (prn_hnd->notify.cli_chan->active_connections == 1) {
277
278                 prn_hnd->notify.cli_chan->binding_handle = NULL;
279                 cli_shutdown(rpc_pipe_np_smb_conn(prn_hnd->notify.cli_chan->cli_pipe));
280                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
281                 TALLOC_FREE(prn_hnd->notify.cli_chan);
282
283                 if (prn_hnd->notify.msg_ctx != NULL) {
284                         messaging_deregister(prn_hnd->notify.msg_ctx,
285                                              MSG_PRINTER_NOTIFY2, NULL);
286
287                         /*
288                          * Tell the serverid.tdb we're no longer
289                          * interested in printer notify messages.
290                          */
291
292                         serverid_register_msg_flags(
293                                 messaging_server_id(prn_hnd->notify.msg_ctx),
294                                 false, FLAG_MSG_PRINT_NOTIFY);
295                 }
296         }
297
298         if (prn_hnd->notify.cli_chan) {
299                 prn_hnd->notify.cli_chan->active_connections--;
300         }
301 }
302
303 /****************************************************************************
304  Functions to free a printer entry datastruct.
305 ****************************************************************************/
306
307 static int printer_entry_destructor(struct printer_handle *Printer)
308 {
309         if (Printer->notify.cli_chan != NULL &&
310             Printer->notify.cli_chan->active_connections > 0) {
311                 int snum = -1;
312
313                 switch(Printer->printer_type) {
314                 case SPLHND_SERVER:
315                         srv_spoolss_replycloseprinter(snum, Printer);
316                         break;
317
318                 case SPLHND_PRINTER:
319                         snum = print_queue_snum(Printer->sharename);
320                         if (snum != -1) {
321                                 srv_spoolss_replycloseprinter(snum, Printer);
322                         }
323                         break;
324                 default:
325                         break;
326                 }
327         }
328
329         Printer->notify.flags=0;
330         Printer->notify.options=0;
331         Printer->notify.localmachine[0]='\0';
332         Printer->notify.printerlocal=0;
333         TALLOC_FREE(Printer->notify.option);
334         TALLOC_FREE(Printer->devmode);
335
336         /* Remove from the internal list. */
337         DLIST_REMOVE(printers_list, Printer);
338         return 0;
339 }
340
341 /****************************************************************************
342   find printer index by handle
343 ****************************************************************************/
344
345 static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
346                                                         struct policy_handle *hnd)
347 {
348         struct printer_handle *find_printer = NULL;
349
350         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
351                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
352                 return NULL;
353         }
354
355         return find_printer;
356 }
357
358 /****************************************************************************
359  Close printer index by handle.
360 ****************************************************************************/
361
362 static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
363 {
364         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
365
366         if (!Printer) {
367                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
368                         OUR_HANDLE(hnd)));
369                 return false;
370         }
371
372         close_policy_hnd(p, hnd);
373
374         return true;
375 }
376
377 /****************************************************************************
378  Delete a printer given a handle.
379 ****************************************************************************/
380
381 static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
382                                   const char *sharename,
383                                   struct messaging_context *msg_ctx)
384 {
385         char *cmd = lp_deleteprinter_cmd();
386         char *command = NULL;
387         int ret;
388         bool is_print_op = false;
389
390         /* can't fail if we don't try */
391
392         if ( !*cmd )
393                 return WERR_OK;
394
395         command = talloc_asprintf(ctx,
396                         "%s \"%s\"",
397                         cmd, sharename);
398         if (!command) {
399                 return WERR_NOMEM;
400         }
401         if ( token )
402                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
403
404         DEBUG(10,("Running [%s]\n", command));
405
406         /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
407
408         if ( is_print_op )
409                 become_root();
410
411         if ( (ret = smbrun(command, NULL)) == 0 ) {
412                 /* Tell everyone we updated smb.conf. */
413                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
414         }
415
416         if ( is_print_op )
417                 unbecome_root();
418
419         /********** END SePrintOperatorPrivlege BLOCK **********/
420
421         DEBUGADD(10,("returned [%d]\n", ret));
422
423         TALLOC_FREE(command);
424
425         if (ret != 0)
426                 return WERR_BADFID; /* What to return here? */
427
428         /* go ahead and re-read the services immediately */
429         become_root();
430         reload_services(msg_ctx, -1, false);
431         unbecome_root();
432
433         if ( lp_servicenumber( sharename ) >= 0 )
434                 return WERR_ACCESS_DENIED;
435
436         return WERR_OK;
437 }
438
439 /****************************************************************************
440  Delete a printer given a handle.
441 ****************************************************************************/
442
443 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
444 {
445         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
446         WERROR result;
447
448         if (!Printer) {
449                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
450                         OUR_HANDLE(hnd)));
451                 return WERR_BADFID;
452         }
453
454         /*
455          * It turns out that Windows allows delete printer on a handle
456          * opened by an admin user, then used on a pipe handle created
457          * by an anonymous user..... but they're working on security.... riiight !
458          * JRA.
459          */
460
461         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
462                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
463                 return WERR_ACCESS_DENIED;
464         }
465
466         /* this does not need a become root since the access check has been
467            done on the handle already */
468
469         result = winreg_delete_printer_key_internal(p->mem_ctx,
470                                            get_session_info_system(),
471                                            p->msg_ctx,
472                                            Printer->sharename,
473                                            "");
474         if (!W_ERROR_IS_OK(result)) {
475                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
476                 return WERR_BADFID;
477         }
478
479         result = delete_printer_hook(p->mem_ctx, p->session_info->security_token,
480                                      Printer->sharename, p->msg_ctx);
481         if (!W_ERROR_IS_OK(result)) {
482                 return result;
483         }
484         prune_printername_cache();
485         return WERR_OK;
486 }
487
488 /****************************************************************************
489  Return the snum of a printer corresponding to an handle.
490 ****************************************************************************/
491
492 static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
493                              int *number, struct share_params **params)
494 {
495         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
496
497         if (!Printer) {
498                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
499                         OUR_HANDLE(hnd)));
500                 return false;
501         }
502
503         switch (Printer->printer_type) {
504                 case SPLHND_PRINTER:
505                         DEBUG(4,("short name:%s\n", Printer->sharename));
506                         *number = print_queue_snum(Printer->sharename);
507                         return (*number != -1);
508                 case SPLHND_SERVER:
509                         return false;
510                 default:
511                         return false;
512         }
513 }
514
515 /****************************************************************************
516  Set printer handle type.
517  Check if it's \\server or \\server\printer
518 ****************************************************************************/
519
520 static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
521 {
522         DEBUG(3,("Setting printer type=%s\n", handlename));
523
524         /* it's a print server */
525         if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
526                 DEBUGADD(4,("Printer is a print server\n"));
527                 Printer->printer_type = SPLHND_SERVER;
528         }
529         /* it's a printer (set_printer_hnd_name() will handle port monitors */
530         else {
531                 DEBUGADD(4,("Printer is a printer\n"));
532                 Printer->printer_type = SPLHND_PRINTER;
533         }
534
535         return true;
536 }
537
538 static void prune_printername_cache_fn(const char *key, const char *value,
539                                        time_t timeout, void *private_data)
540 {
541         gencache_del(key);
542 }
543
544 static void prune_printername_cache(void)
545 {
546         gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
547 }
548
549 /****************************************************************************
550  Set printer handle name..  Accept names like \\server, \\server\printer,
551  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
552  the MSDN docs regarding OpenPrinter() for details on the XcvData() and
553  XcvDataPort() interface.
554 ****************************************************************************/
555
556 static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
557                                    const struct auth_session_info *session_info,
558                                    struct messaging_context *msg_ctx,
559                                    struct printer_handle *Printer,
560                                    const char *handlename)
561 {
562         int snum;
563         int n_services=lp_numservices();
564         char *aprinter;
565         const char *printername;
566         const char *servername = NULL;
567         fstring sname;
568         bool found = false;
569         struct spoolss_PrinterInfo2 *info2 = NULL;
570         WERROR result;
571         char *p;
572
573         /*
574          * Hopefully nobody names his printers like this. Maybe \ or ,
575          * are illegal in printer names even?
576          */
577         const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
578         char *cache_key;
579         char *tmp;
580
581         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
582                 (unsigned long)strlen(handlename)));
583
584         aprinter = discard_const_p(char, handlename);
585         if ( *handlename == '\\' ) {
586                 servername = canon_servername(handlename);
587                 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
588                         *aprinter = '\0';
589                         aprinter++;
590                 }
591                 if (!is_myname_or_ipaddr(servername)) {
592                         return WERR_INVALID_PRINTER_NAME;
593                 }
594                 Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
595                 if (Printer->servername == NULL) {
596                         return WERR_NOMEM;
597                 }
598         }
599
600         if (Printer->printer_type == SPLHND_SERVER) {
601                 return WERR_OK;
602         }
603
604         if (Printer->printer_type != SPLHND_PRINTER) {
605                 return WERR_INVALID_HANDLE;
606         }
607
608         DEBUGADD(5, ("searching for [%s]\n", aprinter));
609
610         p = strchr(aprinter, ',');
611         if (p != NULL) {
612                 char *p2 = p;
613                 p++;
614                 if (*p == ' ') {
615                         p++;
616                 }
617                 if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
618                         *p2 = '\0';
619                 } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
620                         *p2 = '\0';
621                 }
622         }
623
624         if (p) {
625                 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
626         }
627
628         /* check for the Port Monitor Interface */
629         if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
630                 Printer->printer_type = SPLHND_PORTMON_TCP;
631                 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
632                 found = true;
633         }
634         else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
635                 Printer->printer_type = SPLHND_PORTMON_LOCAL;
636                 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
637                 found = true;
638         }
639
640         /*
641          * With hundreds of printers, the "for" loop iterating all
642          * shares can be quite expensive, as it is done on every
643          * OpenPrinter. The loop maps "aprinter" to "sname", the
644          * result of which we cache in gencache.
645          */
646
647         cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s",
648                                     aprinter);
649         if ((cache_key != NULL) && gencache_get(cache_key, &tmp, NULL)) {
650
651                 found = (strcmp(tmp, printer_not_found) != 0);
652                 if (!found) {
653                         DEBUG(4, ("Printer %s not found\n", aprinter));
654                         SAFE_FREE(tmp);
655                         return WERR_INVALID_PRINTER_NAME;
656                 }
657                 fstrcpy(sname, tmp);
658                 SAFE_FREE(tmp);
659         }
660
661         /* Search all sharenames first as this is easier than pulling
662            the printer_info_2 off of disk. Don't use find_service() since
663            that calls out to map_username() */
664
665         /* do another loop to look for printernames */
666         for (snum = 0; !found && snum < n_services; snum++) {
667                 const char *printer = lp_const_servicename(snum);
668
669                 /* no point going on if this is not a printer */
670                 if (!(lp_snum_ok(snum) && lp_print_ok(snum))) {
671                         continue;
672                 }
673
674                 /* ignore [printers] share */
675                 if (strequal(printer, "printers")) {
676                         continue;
677                 }
678
679                 fstrcpy(sname, printer);
680                 if (strequal(aprinter, printer)) {
681                         found = true;
682                         break;
683                 }
684
685                 /* no point looking up the printer object if
686                    we aren't allowing printername != sharename */
687                 if (lp_force_printername(snum)) {
688                         continue;
689                 }
690
691                 result = winreg_get_printer_internal(mem_ctx,
692                                             session_info,
693                                             msg_ctx,
694                                             sname,
695                                             &info2);
696                 if ( !W_ERROR_IS_OK(result) ) {
697                         DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
698                                  sname, win_errstr(result)));
699                         continue;
700                 }
701
702                 printername = strrchr(info2->printername, '\\');
703                 if (printername == NULL) {
704                         printername = info2->printername;
705                 } else {
706                         printername++;
707                 }
708
709                 if (strequal(printername, aprinter)) {
710                         found = true;
711                         break;
712                 }
713
714                 DEBUGADD(10, ("printername: %s\n", printername));
715
716                 TALLOC_FREE(info2);
717         }
718
719         if ( !found ) {
720                 if (cache_key != NULL) {
721                         gencache_set(cache_key, printer_not_found,
722                                      time(NULL)+300);
723                         TALLOC_FREE(cache_key);
724                 }
725                 DEBUGADD(4,("Printer not found\n"));
726                 return WERR_INVALID_PRINTER_NAME;
727         }
728
729         if (cache_key != NULL) {
730                 gencache_set(cache_key, sname, time(NULL)+300);
731                 TALLOC_FREE(cache_key);
732         }
733
734         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
735
736         strlcpy(Printer->sharename, sname, sizeof(Printer->sharename));
737
738         return WERR_OK;
739 }
740
741 /****************************************************************************
742  Find first available printer slot. creates a printer handle for you.
743  ****************************************************************************/
744
745 static WERROR open_printer_hnd(struct pipes_struct *p,
746                                struct policy_handle *hnd,
747                                const char *name,
748                                uint32_t access_granted)
749 {
750         struct printer_handle *new_printer;
751         WERROR result;
752
753         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
754
755         new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
756         if (new_printer == NULL) {
757                 return WERR_NOMEM;
758         }
759         talloc_set_destructor(new_printer, printer_entry_destructor);
760
761         /* This also steals the printer_handle on the policy_handle */
762         if (!create_policy_hnd(p, hnd, new_printer)) {
763                 TALLOC_FREE(new_printer);
764                 return WERR_INVALID_HANDLE;
765         }
766
767         /* Add to the internal list. */
768         DLIST_ADD(printers_list, new_printer);
769
770         new_printer->notify.option=NULL;
771
772         if (!set_printer_hnd_printertype(new_printer, name)) {
773                 close_printer_handle(p, hnd);
774                 return WERR_INVALID_HANDLE;
775         }
776
777         result = set_printer_hnd_name(p->mem_ctx,
778                                       get_session_info_system(),
779                                       p->msg_ctx,
780                                       new_printer, name);
781         if (!W_ERROR_IS_OK(result)) {
782                 close_printer_handle(p, hnd);
783                 return result;
784         }
785
786         new_printer->access_granted = access_granted;
787
788         DEBUG(5, ("%d printer handles active\n",
789                   (int)num_pipe_handles(p)));
790
791         return WERR_OK;
792 }
793
794 /***************************************************************************
795  check to see if the client motify handle is monitoring the notification
796  given by (notify_type, notify_field).
797  **************************************************************************/
798
799 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
800                                       uint16_t notify_field)
801 {
802         return true;
803 }
804
805 static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
806                                 uint16_t notify_field)
807 {
808         struct spoolss_NotifyOption *option = p->notify.option;
809         uint32_t i, j;
810
811         /*
812          * Flags should always be zero when the change notify
813          * is registered by the client's spooler.  A user Win32 app
814          * might use the flags though instead of the NOTIFY_OPTION_INFO
815          * --jerry
816          */
817
818         if (!option) {
819                 return false;
820         }
821
822         if (p->notify.flags)
823                 return is_monitoring_event_flags(
824                         p->notify.flags, notify_type, notify_field);
825
826         for (i = 0; i < option->count; i++) {
827
828                 /* Check match for notify_type */
829
830                 if (option->types[i].type != notify_type)
831                         continue;
832
833                 /* Check match for field */
834
835                 for (j = 0; j < option->types[i].count; j++) {
836                         if (option->types[i].fields[j].field == notify_field) {
837                                 return true;
838                         }
839                 }
840         }
841
842         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
843                    p->servername, p->sharename, notify_type, notify_field));
844
845         return false;
846 }
847
848 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
849         _data->data.integer[0] = _integer; \
850         _data->data.integer[1] = 0;
851
852
853 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
854         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
855         if (!_data->data.string.string) {\
856                 _data->data.string.size = 0; \
857         } \
858         _data->data.string.size = strlen_m_term(_p) * 2;
859
860 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
861         _data->data.devmode.devmode = _devmode;
862
863 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
864         _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
865         if (!_data->data.sd.sd) { \
866                 _data->data.sd.sd_size = 0; \
867         } \
868         _data->data.sd.sd_size = \
869                 ndr_size_security_descriptor(_data->data.sd.sd, 0);
870
871 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
872                                    struct tm *t,
873                                    const char **pp,
874                                    uint32_t *plen)
875 {
876         struct spoolss_Time st;
877         uint32_t len = 16;
878         char *p;
879
880         if (!init_systemtime(&st, t)) {
881                 return;
882         }
883
884         p = talloc_array(mem_ctx, char, len);
885         if (!p) {
886                 return;
887         }
888
889         /*
890          * Systemtime must be linearized as a set of UINT16's.
891          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
892          */
893
894         SSVAL(p, 0, st.year);
895         SSVAL(p, 2, st.month);
896         SSVAL(p, 4, st.day_of_week);
897         SSVAL(p, 6, st.day);
898         SSVAL(p, 8, st.hour);
899         SSVAL(p, 10, st.minute);
900         SSVAL(p, 12, st.second);
901         SSVAL(p, 14, st.millisecond);
902
903         *pp = p;
904         *plen = len;
905 }
906
907 /* Convert a notification message to a struct spoolss_Notify */
908
909 static void notify_one_value(struct spoolss_notify_msg *msg,
910                              struct spoolss_Notify *data,
911                              TALLOC_CTX *mem_ctx)
912 {
913         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
914 }
915
916 static void notify_string(struct spoolss_notify_msg *msg,
917                           struct spoolss_Notify *data,
918                           TALLOC_CTX *mem_ctx)
919 {
920         /* The length of the message includes the trailing \0 */
921
922         data->data.string.size = msg->len * 2;
923         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
924         if (!data->data.string.string) {
925                 data->data.string.size = 0;
926                 return;
927         }
928 }
929
930 static void notify_system_time(struct spoolss_notify_msg *msg,
931                                struct spoolss_Notify *data,
932                                TALLOC_CTX *mem_ctx)
933 {
934         data->data.string.string = NULL;
935         data->data.string.size = 0;
936
937         if (msg->len != sizeof(time_t)) {
938                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
939                           msg->len));
940                 return;
941         }
942
943         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
944                                &data->data.string.string,
945                                &data->data.string.size);
946 }
947
948 struct notify2_message_table {
949         const char *name;
950         void (*fn)(struct spoolss_notify_msg *msg,
951                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
952 };
953
954 static struct notify2_message_table printer_notify_table[] = {
955         /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
956         /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
957         /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
958         /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
959         /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
960         /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
961         /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
962         /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
963         /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
964         /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
965         /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
966         /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
967         /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
968         /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
969         /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
970         /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
971         /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
972         /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
973         /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
974 };
975
976 static struct notify2_message_table job_notify_table[] = {
977         /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
978         /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
979         /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
980         /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
981         /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
982         /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
983         /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
984         /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
985         /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
986         /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
987         /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
988         /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
989         /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
990         /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
991         /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
992         /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
993         /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
994         /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
995         /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
996         /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
997         /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
998         /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
999         /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
1000         /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
1001 };
1002
1003
1004 /***********************************************************************
1005  Allocate talloc context for container object
1006  **********************************************************************/
1007
1008 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1009 {
1010         if ( !ctr )
1011                 return;
1012
1013         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
1014
1015         return;
1016 }
1017
1018 /***********************************************************************
1019  release all allocated memory and zero out structure
1020  **********************************************************************/
1021
1022 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1023 {
1024         if ( !ctr )
1025                 return;
1026
1027         if ( ctr->ctx )
1028                 talloc_destroy(ctr->ctx);
1029
1030         ZERO_STRUCTP(ctr);
1031
1032         return;
1033 }
1034
1035 /***********************************************************************
1036  **********************************************************************/
1037
1038 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1039 {
1040         if ( !ctr )
1041                 return NULL;
1042
1043         return ctr->ctx;
1044 }
1045
1046 /***********************************************************************
1047  **********************************************************************/
1048
1049 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1050 {
1051         if ( !ctr || !ctr->msg_groups )
1052                 return NULL;
1053
1054         if ( idx >= ctr->num_groups )
1055                 return NULL;
1056
1057         return &ctr->msg_groups[idx];
1058
1059 }
1060
1061 /***********************************************************************
1062  How many groups of change messages do we have ?
1063  **********************************************************************/
1064
1065 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1066 {
1067         if ( !ctr )
1068                 return 0;
1069
1070         return ctr->num_groups;
1071 }
1072
1073 /***********************************************************************
1074  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1075  **********************************************************************/
1076
1077 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1078 {
1079         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
1080         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
1081         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
1082         int                             i, new_slot;
1083
1084         if ( !ctr || !msg )
1085                 return 0;
1086
1087         /* loop over all groups looking for a matching printer name */
1088
1089         for ( i=0; i<ctr->num_groups; i++ ) {
1090                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1091                         break;
1092         }
1093
1094         /* add a new group? */
1095
1096         if ( i == ctr->num_groups ) {
1097                 ctr->num_groups++;
1098
1099                 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1100                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1101                         return 0;
1102                 }
1103                 ctr->msg_groups = groups;
1104
1105                 /* clear the new entry and set the printer name */
1106
1107                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1108                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1109         }
1110
1111         /* add the change messages; 'i' is the correct index now regardless */
1112
1113         msg_grp = &ctr->msg_groups[i];
1114
1115         msg_grp->num_msgs++;
1116
1117         if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1118                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1119                 return 0;
1120         }
1121         msg_grp->msgs = msg_list;
1122
1123         new_slot = msg_grp->num_msgs-1;
1124         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1125
1126         /* need to allocate own copy of data */
1127
1128         if ( msg->len != 0 )
1129                 msg_grp->msgs[new_slot].notify.data = (char *)
1130                         talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
1131
1132         return ctr->num_groups;
1133 }
1134
1135 static void construct_info_data(struct spoolss_Notify *info_data,
1136                                 enum spoolss_NotifyType type,
1137                                 uint16_t field, int id);
1138
1139 /***********************************************************************
1140  Send a change notication message on all handles which have a call
1141  back registered
1142  **********************************************************************/
1143
1144 static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1145                                   struct printer_handle *prn_hnd,
1146                                   SPOOLSS_NOTIFY_MSG *messages,
1147                                   uint32_t num_msgs,
1148                                   struct spoolss_Notify **_notifies,
1149                                   int *_count)
1150 {
1151         struct spoolss_Notify *notifies;
1152         SPOOLSS_NOTIFY_MSG *msg;
1153         int count = 0;
1154         uint32_t id;
1155         int i;
1156
1157         notifies = talloc_zero_array(mem_ctx,
1158                                      struct spoolss_Notify, num_msgs);
1159         if (!notifies) {
1160                 return ENOMEM;
1161         }
1162
1163         for (i = 0; i < num_msgs; i++) {
1164
1165                 msg = &messages[i];
1166
1167                 /* Are we monitoring this event? */
1168
1169                 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1170                         continue;
1171                 }
1172
1173                 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1174                            "for printer [%s]\n",
1175                            msg->type, msg->field, prn_hnd->sharename));
1176
1177                 /*
1178                  * if the is a printer notification handle and not a job
1179                  * notification type, then set the id to 0.
1180                  * Otherwise just use what was specified in the message.
1181                  *
1182                  * When registering change notification on a print server
1183                  * handle we always need to send back the id (snum) matching
1184                  * the printer for which the change took place.
1185                  * For change notify registered on a printer handle,
1186                  * this does not matter and the id should be 0.
1187                  *
1188                  * --jerry
1189                  */
1190
1191                 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1192                     (prn_hnd->printer_type == SPLHND_PRINTER)) {
1193                         id = 0;
1194                 } else {
1195                         id = msg->id;
1196                 }
1197
1198                 /* Convert unix jobid to smb jobid */
1199
1200                 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1201                         id = sysjob_to_jobid(msg->id);
1202
1203                         if (id == -1) {
1204                                 DEBUG(3, ("no such unix jobid %d\n",
1205                                           msg->id));
1206                                 continue;
1207                         }
1208                 }
1209
1210                 construct_info_data(&notifies[count],
1211                                     msg->type, msg->field, id);
1212
1213                 switch(msg->type) {
1214                 case PRINTER_NOTIFY_TYPE:
1215                         if (printer_notify_table[msg->field].fn) {
1216                                 printer_notify_table[msg->field].fn(msg,
1217                                                 &notifies[count], mem_ctx);
1218                         }
1219                         break;
1220
1221                 case JOB_NOTIFY_TYPE:
1222                         if (job_notify_table[msg->field].fn) {
1223                                 job_notify_table[msg->field].fn(msg,
1224                                                 &notifies[count], mem_ctx);
1225                         }
1226                         break;
1227
1228                 default:
1229                         DEBUG(5, ("Unknown notification type %d\n",
1230                                   msg->type));
1231                         continue;
1232                 }
1233
1234                 count++;
1235         }
1236
1237         *_notifies = notifies;
1238         *_count = count;
1239
1240         return 0;
1241 }
1242
1243 static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1244                                 struct printer_handle *prn_hnd,
1245                                 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1246 {
1247         struct spoolss_Notify *notifies;
1248         int count = 0;
1249         union spoolss_ReplyPrinterInfo info;
1250         struct spoolss_NotifyInfo info0;
1251         uint32_t reply_result;
1252         NTSTATUS status;
1253         WERROR werr;
1254         int ret;
1255
1256         /* Is there notification on this handle? */
1257         if (prn_hnd->notify.cli_chan == NULL ||
1258             prn_hnd->notify.cli_chan->active_connections == 0) {
1259                 return 0;
1260         }
1261
1262         DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1263                    prn_hnd->servername, prn_hnd->sharename));
1264
1265         /* For this printer? Print servers always receive notifications. */
1266         if ((prn_hnd->printer_type == SPLHND_PRINTER)  &&
1267             (!strequal(msg_group->printername, prn_hnd->sharename))) {
1268                 return 0;
1269         }
1270
1271         DEBUG(10,("Our printer\n"));
1272
1273         /* build the array of change notifications */
1274         ret = build_notify2_messages(mem_ctx, prn_hnd,
1275                                      msg_group->msgs,
1276                                      msg_group->num_msgs,
1277                                      &notifies, &count);
1278         if (ret) {
1279                 return ret;
1280         }
1281
1282         info0.version   = 0x2;
1283         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1284         info0.count     = count;
1285         info0.notifies  = notifies;
1286
1287         info.info0 = &info0;
1288
1289         status = dcerpc_spoolss_RouterReplyPrinterEx(
1290                                 prn_hnd->notify.cli_chan->binding_handle,
1291                                 mem_ctx,
1292                                 &prn_hnd->notify.cli_hnd,
1293                                 prn_hnd->notify.change, /* color */
1294                                 prn_hnd->notify.flags,
1295                                 &reply_result,
1296                                 0, /* reply_type, must be 0 */
1297                                 info, &werr);
1298         if (!NT_STATUS_IS_OK(status)) {
1299                 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1300                           "failed: %s\n",
1301                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1302                           nt_errstr(status)));
1303                 werr = ntstatus_to_werror(status);
1304         } else if (!W_ERROR_IS_OK(werr)) {
1305                 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1306                           "failed: %s\n",
1307                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1308                           win_errstr(werr)));
1309         }
1310         switch (reply_result) {
1311         case 0:
1312                 break;
1313         case PRINTER_NOTIFY_INFO_DISCARDED:
1314         case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1315         case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1316                 break;
1317         default:
1318                 break;
1319         }
1320
1321         return 0;
1322 }
1323
1324 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1325 {
1326         struct printer_handle    *p;
1327         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
1328         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1329         int ret;
1330
1331         if ( !msg_group ) {
1332                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1333                 return;
1334         }
1335
1336         if (!msg_group->msgs) {
1337                 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1338                 return;
1339         }
1340
1341         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1342
1343         /* loop over all printers */
1344
1345         for (p = printers_list; p; p = p->next) {
1346                 ret = send_notify2_printer(mem_ctx, p, msg_group);
1347                 if (ret) {
1348                         goto done;
1349                 }
1350         }
1351
1352 done:
1353         DEBUG(8,("send_notify2_changes: Exit...\n"));
1354         return;
1355 }
1356
1357 /***********************************************************************
1358  **********************************************************************/
1359
1360 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1361 {
1362
1363         uint32_t tv_sec, tv_usec;
1364         size_t offset = 0;
1365
1366         /* Unpack message */
1367
1368         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1369                              msg->printer);
1370
1371         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1372                                 &tv_sec, &tv_usec,
1373                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1374
1375         if (msg->len == 0)
1376                 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1377                            &msg->notify.value[0], &msg->notify.value[1]);
1378         else
1379                 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1380                            &msg->len, &msg->notify.data);
1381
1382         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1383                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1384
1385         tv->tv_sec = tv_sec;
1386         tv->tv_usec = tv_usec;
1387
1388         if (msg->len == 0)
1389                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1390                           msg->notify.value[1]));
1391         else
1392                 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1393
1394         return true;
1395 }
1396
1397 /********************************************************************
1398  Receive a notify2 message list
1399  ********************************************************************/
1400
1401 static void receive_notify2_message_list(struct messaging_context *msg,
1402                                          void *private_data,
1403                                          uint32_t msg_type,
1404                                          struct server_id server_id,
1405                                          DATA_BLOB *data)
1406 {
1407         size_t                  msg_count, i;
1408         char                    *buf = (char *)data->data;
1409         char                    *msg_ptr;
1410         size_t                  msg_len;
1411         SPOOLSS_NOTIFY_MSG      notify;
1412         SPOOLSS_NOTIFY_MSG_CTR  messages;
1413         int                     num_groups;
1414
1415         if (data->length < 4) {
1416                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1417                 return;
1418         }
1419
1420         msg_count = IVAL(buf, 0);
1421         msg_ptr = buf + 4;
1422
1423         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1424
1425         if (msg_count == 0) {
1426                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1427                 return;
1428         }
1429
1430         /* initialize the container */
1431
1432         ZERO_STRUCT( messages );
1433         notify_msg_ctr_init( &messages );
1434
1435         /*
1436          * build message groups for each printer identified
1437          * in a change_notify msg.  Remember that a PCN message
1438          * includes the handle returned for the srv_spoolss_replyopenprinter()
1439          * call.  Therefore messages are grouped according to printer handle.
1440          */
1441
1442         for ( i=0; i<msg_count; i++ ) {
1443                 struct timeval msg_tv;
1444
1445                 if (msg_ptr + 4 - buf > data->length) {
1446                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1447                         return;
1448                 }
1449
1450                 msg_len = IVAL(msg_ptr,0);
1451                 msg_ptr += 4;
1452
1453                 if (msg_ptr + msg_len - buf > data->length) {
1454                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1455                         return;
1456                 }
1457
1458                 /* unpack messages */
1459
1460                 ZERO_STRUCT( notify );
1461                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1462                 msg_ptr += msg_len;
1463
1464                 /* add to correct list in container */
1465
1466                 notify_msg_ctr_addmsg( &messages, &notify );
1467
1468                 /* free memory that might have been allocated by notify2_unpack_msg() */
1469
1470                 if ( notify.len != 0 )
1471                         SAFE_FREE( notify.notify.data );
1472         }
1473
1474         /* process each group of messages */
1475
1476         num_groups = notify_msg_ctr_numgroups( &messages );
1477         for ( i=0; i<num_groups; i++ )
1478                 send_notify2_changes( &messages, i );
1479
1480
1481         /* cleanup */
1482
1483         DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1484                 (uint32_t)msg_count ));
1485
1486         notify_msg_ctr_destroy( &messages );
1487
1488         return;
1489 }
1490
1491 /********************************************************************
1492  Send a message to ourself about new driver being installed
1493  so we can upgrade the information for each printer bound to this
1494  driver
1495  ********************************************************************/
1496
1497 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1498                                             struct messaging_context *msg_ctx)
1499 {
1500         int len = strlen(drivername);
1501
1502         if (!len)
1503                 return false;
1504
1505         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1506                 drivername));
1507
1508         messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1509                            MSG_PRINTER_DRVUPGRADE,
1510                            (const uint8_t *)drivername, len+1);
1511
1512         return true;
1513 }
1514
1515 void srv_spoolss_cleanup(void)
1516 {
1517         struct printer_session_counter *session_counter;
1518
1519         for (session_counter = counter_list;
1520              session_counter != NULL;
1521              session_counter = counter_list) {
1522                 DLIST_REMOVE(counter_list, session_counter);
1523                 TALLOC_FREE(session_counter);
1524         }
1525 }
1526
1527 /**********************************************************************
1528  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1529  over all printers, upgrading ones as necessary
1530  **********************************************************************/
1531
1532 void do_drv_upgrade_printer(struct messaging_context *msg,
1533                             void *private_data,
1534                             uint32_t msg_type,
1535                             struct server_id server_id,
1536                             DATA_BLOB *data)
1537 {
1538         TALLOC_CTX *tmp_ctx;
1539         const struct auth_session_info *session_info = get_session_info_system();
1540         struct spoolss_PrinterInfo2 *pinfo2;
1541         WERROR result;
1542         const char *drivername;
1543         int snum;
1544         int n_services = lp_numservices();
1545         struct dcerpc_binding_handle *b = NULL;
1546
1547         tmp_ctx = talloc_new(NULL);
1548         if (!tmp_ctx) return;
1549
1550         drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1551         if (!drivername) {
1552                 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1553                 goto done;
1554         }
1555
1556         DEBUG(10, ("do_drv_upgrade_printer: "
1557                    "Got message for new driver [%s]\n", drivername));
1558
1559         /* Iterate the printer list */
1560
1561         for (snum = 0; snum < n_services; snum++) {
1562                 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1563                         continue;
1564                 }
1565
1566                 /* ignore [printers] share */
1567                 if (strequal(lp_const_servicename(snum), "printers")) {
1568                         continue;
1569                 }
1570
1571                 if (b == NULL) {
1572                         result = winreg_printer_binding_handle(tmp_ctx,
1573                                                                session_info,
1574                                                                msg,
1575                                                                &b);
1576                         if (!W_ERROR_IS_OK(result)) {
1577                                 break;
1578                         }
1579                 }
1580
1581                 result = winreg_get_printer(tmp_ctx, b,
1582                                             lp_const_servicename(snum),
1583                                             &pinfo2);
1584
1585                 if (!W_ERROR_IS_OK(result)) {
1586                         continue;
1587                 }
1588
1589                 if (!pinfo2->drivername) {
1590                         continue;
1591                 }
1592
1593                 if (strcmp(drivername, pinfo2->drivername) != 0) {
1594                         continue;
1595                 }
1596
1597                 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1598
1599                 /* all we care about currently is the change_id */
1600                 result = winreg_printer_update_changeid(tmp_ctx, b,
1601                                                         pinfo2->printername);
1602
1603                 if (!W_ERROR_IS_OK(result)) {
1604                         DEBUG(3, ("do_drv_upgrade_printer: "
1605                                   "Failed to update changeid [%s]\n",
1606                                   win_errstr(result)));
1607                 }
1608         }
1609
1610         /* all done */
1611 done:
1612         talloc_free(tmp_ctx);
1613 }
1614
1615 /********************************************************************
1616  Update the cache for all printq's with a registered client
1617  connection
1618  ********************************************************************/
1619
1620 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1621 {
1622         struct printer_handle *printer = printers_list;
1623         int snum;
1624
1625         /* loop through all printers and update the cache where
1626            a client is connected */
1627         while (printer) {
1628                 if ((printer->printer_type == SPLHND_PRINTER) &&
1629                     ((printer->notify.cli_chan != NULL) &&
1630                      (printer->notify.cli_chan->active_connections > 0))) {
1631                         snum = print_queue_snum(printer->sharename);
1632                         print_queue_status(msg_ctx, snum, NULL, NULL);
1633                 }
1634
1635                 printer = printer->next;
1636         }
1637
1638         return;
1639 }
1640
1641 /****************************************************************
1642  _spoolss_OpenPrinter
1643 ****************************************************************/
1644
1645 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1646                             struct spoolss_OpenPrinter *r)
1647 {
1648         struct spoolss_OpenPrinterEx e;
1649         WERROR werr;
1650
1651         ZERO_STRUCT(e.in.userlevel);
1652
1653         e.in.printername        = r->in.printername;
1654         e.in.datatype           = r->in.datatype;
1655         e.in.devmode_ctr        = r->in.devmode_ctr;
1656         e.in.access_mask        = r->in.access_mask;
1657         e.in.level              = 0;
1658
1659         e.out.handle            = r->out.handle;
1660
1661         werr = _spoolss_OpenPrinterEx(p, &e);
1662
1663         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1664                 /* OpenPrinterEx returns this for a bad
1665                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1666                  * instead.
1667                  */
1668                 werr = WERR_INVALID_PRINTER_NAME;
1669         }
1670
1671         return werr;
1672 }
1673
1674 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1675                               struct spoolss_DeviceMode *orig,
1676                               struct spoolss_DeviceMode **dest)
1677 {
1678         struct spoolss_DeviceMode *dm;
1679
1680         dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1681         if (!dm) {
1682                 return WERR_NOMEM;
1683         }
1684
1685         /* copy all values, then duplicate strings and structs */
1686         *dm = *orig;
1687
1688         dm->devicename = talloc_strdup(dm, orig->devicename);
1689         if (!dm->devicename) {
1690                 return WERR_NOMEM;
1691         }
1692         dm->formname = talloc_strdup(dm, orig->formname);
1693         if (!dm->formname) {
1694                 return WERR_NOMEM;
1695         }
1696         if (orig->driverextra_data.data) {
1697                 dm->driverextra_data.data =
1698                         (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1699                                         orig->driverextra_data.length);
1700                 if (!dm->driverextra_data.data) {
1701                         return WERR_NOMEM;
1702                 }
1703         }
1704
1705         *dest = dm;
1706         return WERR_OK;
1707 }
1708
1709 /****************************************************************
1710  _spoolss_OpenPrinterEx
1711 ****************************************************************/
1712
1713 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1714                               struct spoolss_OpenPrinterEx *r)
1715 {
1716         int snum;
1717         char *raddr;
1718         char *rhost;
1719         struct printer_handle *Printer=NULL;
1720         WERROR result;
1721         int rc;
1722
1723         if (!r->in.printername) {
1724                 return WERR_INVALID_PARAM;
1725         }
1726
1727         if (r->in.level > 3) {
1728                 return WERR_INVALID_PARAM;
1729         }
1730         if ((r->in.level == 1 && !r->in.userlevel.level1) ||
1731             (r->in.level == 2 && !r->in.userlevel.level2) ||
1732             (r->in.level == 3 && !r->in.userlevel.level3)) {
1733                 return WERR_INVALID_PARAM;
1734         }
1735
1736         /* some sanity check because you can open a printer or a print server */
1737         /* aka: \\server\printer or \\server */
1738
1739         DEBUGADD(3,("checking name: %s\n", r->in.printername));
1740
1741         result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1742         if (!W_ERROR_IS_OK(result)) {
1743                 DEBUG(0,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1744                         "for printer %s\n", r->in.printername));
1745                 ZERO_STRUCTP(r->out.handle);
1746                 return result;
1747         }
1748
1749         Printer = find_printer_index_by_hnd(p, r->out.handle);
1750         if ( !Printer ) {
1751                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1752                         "handle we created for printer %s\n", r->in.printername));
1753                 close_printer_handle(p, r->out.handle);
1754                 ZERO_STRUCTP(r->out.handle);
1755                 return WERR_INVALID_PARAM;
1756         }
1757
1758         /*
1759          * First case: the user is opening the print server:
1760          *
1761          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1762          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1763          *
1764          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1765          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1766          * or if the user is listed in the smb.conf printer admin parameter.
1767          *
1768          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1769          * client view printer folder, but does not show the MSAPW.
1770          *
1771          * Note: this test needs code to check access rights here too. Jeremy
1772          * could you look at this?
1773          *
1774          * Second case: the user is opening a printer:
1775          * NT doesn't let us connect to a printer if the connecting user
1776          * doesn't have print permission.
1777          *
1778          * Third case: user is opening a Port Monitor
1779          * access checks same as opening a handle to the print server.
1780          */
1781
1782         switch (Printer->printer_type )
1783         {
1784         case SPLHND_SERVER:
1785         case SPLHND_PORTMON_TCP:
1786         case SPLHND_PORTMON_LOCAL:
1787                 /* Printserver handles use global struct... */
1788
1789                 snum = -1;
1790
1791                 /* Map standard access rights to object specific access rights */
1792
1793                 se_map_standard(&r->in.access_mask,
1794                                 &printserver_std_mapping);
1795
1796                 /* Deny any object specific bits that don't apply to print
1797                    servers (i.e printer and job specific bits) */
1798
1799                 r->in.access_mask &= SEC_MASK_SPECIFIC;
1800
1801                 if (r->in.access_mask &
1802                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1803                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1804                         close_printer_handle(p, r->out.handle);
1805                         ZERO_STRUCTP(r->out.handle);
1806                         return WERR_ACCESS_DENIED;
1807                 }
1808
1809                 /* Allow admin access */
1810
1811                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1812                 {
1813                         if (!lp_ms_add_printer_wizard()) {
1814                                 close_printer_handle(p, r->out.handle);
1815                                 ZERO_STRUCTP(r->out.handle);
1816                                 return WERR_ACCESS_DENIED;
1817                         }
1818
1819                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1820                            and not a printer admin, then fail */
1821
1822                         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
1823                             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
1824                             !nt_token_check_sid(&global_sid_Builtin_Print_Operators, p->session_info->security_token) &&
1825                             !token_contains_name_in_list(
1826                                     uidtoname(p->session_info->unix_token->uid),
1827                                     p->session_info->info->domain_name,
1828                                     NULL,
1829                                     p->session_info->security_token,
1830                                     lp_printer_admin(snum))) {
1831                                 close_printer_handle(p, r->out.handle);
1832                                 ZERO_STRUCTP(r->out.handle);
1833                                 DEBUG(3,("access DENIED as user is not root, "
1834                                         "has no printoperator privilege, "
1835                                         "not a member of the printoperator builtin group and "
1836                                         "is not in printer admin list"));
1837                                 return WERR_ACCESS_DENIED;
1838                         }
1839
1840                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1841                 }
1842                 else
1843                 {
1844                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1845                 }
1846
1847                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1848                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1849
1850                 /* We fall through to return WERR_OK */
1851                 break;
1852
1853         case SPLHND_PRINTER:
1854                 /* NT doesn't let us connect to a printer if the connecting user
1855                    doesn't have print permission.  */
1856
1857                 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1858                         close_printer_handle(p, r->out.handle);
1859                         ZERO_STRUCTP(r->out.handle);
1860                         return WERR_BADFID;
1861                 }
1862
1863                 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1864                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1865                 }
1866
1867                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1868
1869                 /* map an empty access mask to the minimum access mask */
1870                 if (r->in.access_mask == 0x0)
1871                         r->in.access_mask = PRINTER_ACCESS_USE;
1872
1873                 /*
1874                  * If we are not serving the printer driver for this printer,
1875                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1876                  * will keep NT clients happy  --jerry
1877                  */
1878
1879                 if (lp_use_client_driver(snum)
1880                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1881                 {
1882                         r->in.access_mask = PRINTER_ACCESS_USE;
1883                 }
1884
1885                 /* check smb.conf parameters and the the sec_desc */
1886                 raddr = tsocket_address_inet_addr_string(p->remote_address,
1887                                                          p->mem_ctx);
1888                 if (raddr == NULL) {
1889                         return WERR_NOMEM;
1890                 }
1891
1892                 rc = get_remote_hostname(p->remote_address,
1893                                          &rhost,
1894                                          p->mem_ctx);
1895                 if (rc < 0) {
1896                         return WERR_NOMEM;
1897                 }
1898                 if (strequal(rhost, "UNKNOWN")) {
1899                         rhost = raddr;
1900                 }
1901
1902                 if (!allow_access(lp_hostsdeny(snum), lp_hostsallow(snum),
1903                                   rhost, raddr)) {
1904                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1905                         ZERO_STRUCTP(r->out.handle);
1906                         return WERR_ACCESS_DENIED;
1907                 }
1908
1909                 if (!user_ok_token(uidtoname(p->session_info->unix_token->uid), NULL,
1910                                    p->session_info->security_token, snum) ||
1911                     !print_access_check(p->session_info,
1912                                         p->msg_ctx,
1913                                         snum,
1914                                         r->in.access_mask)) {
1915                         DEBUG(3, ("access DENIED for printer open\n"));
1916                         close_printer_handle(p, r->out.handle);
1917                         ZERO_STRUCTP(r->out.handle);
1918                         return WERR_ACCESS_DENIED;
1919                 }
1920
1921                 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1922                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1923                         close_printer_handle(p, r->out.handle);
1924                         ZERO_STRUCTP(r->out.handle);
1925                         return WERR_ACCESS_DENIED;
1926                 }
1927
1928                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1929                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1930                 else
1931                         r->in.access_mask = PRINTER_ACCESS_USE;
1932
1933                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1934                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1935
1936                 winreg_create_printer_internal(p->mem_ctx,
1937                                       get_session_info_system(),
1938                                       p->msg_ctx,
1939                                       lp_const_servicename(snum));
1940
1941                 break;
1942
1943         default:
1944                 /* sanity check to prevent programmer error */
1945                 ZERO_STRUCTP(r->out.handle);
1946                 return WERR_BADFID;
1947         }
1948
1949         Printer->access_granted = r->in.access_mask;
1950
1951         /*
1952          * If the client sent a devmode in the OpenPrinter() call, then
1953          * save it here in case we get a job submission on this handle
1954          */
1955
1956          if ((Printer->printer_type != SPLHND_SERVER) &&
1957              r->in.devmode_ctr.devmode) {
1958                 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1959                                 &Printer->devmode);
1960          }
1961
1962 #if 0   /* JERRY -- I'm doubtful this is really effective */
1963         /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1964            optimization in Windows 2000 clients  --jerry */
1965
1966         if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1967                 && (RA_WIN2K == get_remote_arch()) )
1968         {
1969                 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1970                 sys_usleep( 500000 );
1971         }
1972 #endif
1973
1974         return WERR_OK;
1975 }
1976
1977 /****************************************************************
1978  _spoolss_ClosePrinter
1979 ****************************************************************/
1980
1981 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1982                              struct spoolss_ClosePrinter *r)
1983 {
1984         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1985
1986         if (Printer && Printer->document_started) {
1987                 struct spoolss_EndDocPrinter e;
1988
1989                 e.in.handle = r->in.handle;
1990
1991                 _spoolss_EndDocPrinter(p, &e);
1992         }
1993
1994         if (!close_printer_handle(p, r->in.handle))
1995                 return WERR_BADFID;
1996
1997         /* clear the returned printer handle.  Observed behavior
1998            from Win2k server.  Don't think this really matters.
1999            Previous code just copied the value of the closed
2000            handle.    --jerry */
2001
2002         ZERO_STRUCTP(r->out.handle);
2003
2004         return WERR_OK;
2005 }
2006
2007 /****************************************************************
2008  _spoolss_DeletePrinter
2009 ****************************************************************/
2010
2011 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
2012                               struct spoolss_DeletePrinter *r)
2013 {
2014         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2015         WERROR result;
2016         int snum;
2017
2018         if (Printer && Printer->document_started) {
2019                 struct spoolss_EndDocPrinter e;
2020
2021                 e.in.handle = r->in.handle;
2022
2023                 _spoolss_EndDocPrinter(p, &e);
2024         }
2025
2026         if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
2027                 winreg_delete_printer_key_internal(p->mem_ctx,
2028                                           get_session_info_system(),
2029                                           p->msg_ctx,
2030                                           lp_const_servicename(snum),
2031                                           "");
2032         }
2033
2034         result = delete_printer_handle(p, r->in.handle);
2035
2036         return result;
2037 }
2038
2039 /*******************************************************************
2040  * static function to lookup the version id corresponding to an
2041  * long architecture string
2042  ******************************************************************/
2043
2044 static const struct print_architecture_table_node archi_table[]= {
2045
2046         {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
2047         {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
2048         {"Windows NT R4000",     SPL_ARCH_W32MIPS,      2 },
2049         {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,     2 },
2050         {"Windows NT PowerPC",   SPL_ARCH_W32PPC,       2 },
2051         {"Windows IA64",         SPL_ARCH_IA64,         3 },
2052         {"Windows x64",          SPL_ARCH_X64,          3 },
2053         {NULL,                   "",            -1 }
2054 };
2055
2056 static int get_version_id(const char *arch)
2057 {
2058         int i;
2059
2060         for (i=0; archi_table[i].long_archi != NULL; i++)
2061         {
2062                 if (strcmp(arch, archi_table[i].long_archi) == 0)
2063                         return (archi_table[i].version);
2064         }
2065
2066         return -1;
2067 }
2068
2069 /****************************************************************
2070  _spoolss_DeletePrinterDriver
2071 ****************************************************************/
2072
2073 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2074                                     struct spoolss_DeletePrinterDriver *r)
2075 {
2076
2077         struct spoolss_DriverInfo8 *info = NULL;
2078         struct spoolss_DriverInfo8 *info_win2k = NULL;
2079         int                             version;
2080         WERROR                          status;
2081         struct dcerpc_binding_handle *b;
2082         TALLOC_CTX *tmp_ctx = NULL;
2083
2084         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2085            and not a printer admin, then fail */
2086
2087         if ( (p->session_info->unix_token->uid != sec_initial_uid())
2088              && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2089                 && !token_contains_name_in_list(
2090                         uidtoname(p->session_info->unix_token->uid),
2091                         p->session_info->info->domain_name,
2092                         NULL,
2093                         p->session_info->security_token,
2094                         lp_printer_admin(-1)) )
2095         {
2096                 return WERR_ACCESS_DENIED;
2097         }
2098
2099         /* check that we have a valid driver name first */
2100
2101         if ((version = get_version_id(r->in.architecture)) == -1) {
2102                 return WERR_INVALID_ENVIRONMENT;
2103         }
2104
2105         tmp_ctx = talloc_new(p->mem_ctx);
2106         if (!tmp_ctx) {
2107                 return WERR_NOMEM;
2108         }
2109
2110         status = winreg_printer_binding_handle(tmp_ctx,
2111                                                get_session_info_system(),
2112                                                p->msg_ctx,
2113                                                &b);
2114         if (!W_ERROR_IS_OK(status)) {
2115                 goto done;
2116         }
2117
2118         status = winreg_get_driver(tmp_ctx, b,
2119                                    r->in.architecture, r->in.driver,
2120                                    version, &info);
2121         if (!W_ERROR_IS_OK(status)) {
2122                 /* try for Win2k driver if "Windows NT x86" */
2123
2124                 if ( version == 2 ) {
2125                         version = 3;
2126
2127                         status = winreg_get_driver(tmp_ctx, b,
2128                                                    r->in.architecture,
2129                                                    r->in.driver,
2130                                                    version, &info);
2131                         if (!W_ERROR_IS_OK(status)) {
2132                                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2133                                 goto done;
2134                         }
2135                 }
2136                 /* otherwise it was a failure */
2137                 else {
2138                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2139                         goto done;
2140                 }
2141
2142         }
2143
2144         if (printer_driver_in_use(tmp_ctx,
2145                                   get_session_info_system(),
2146                                   p->msg_ctx,
2147                                   info)) {
2148                 status = WERR_PRINTER_DRIVER_IN_USE;
2149                 goto done;
2150         }
2151
2152         if (version == 2) {
2153                 status = winreg_get_driver(tmp_ctx, b,
2154                                            r->in.architecture,
2155                                            r->in.driver, 3, &info_win2k);
2156                 if (W_ERROR_IS_OK(status)) {
2157                         /* if we get to here, we now have 2 driver info structures to remove */
2158                         /* remove the Win2k driver first*/
2159
2160                         status = winreg_del_driver(tmp_ctx, b,
2161                                                    info_win2k, 3);
2162                         talloc_free(info_win2k);
2163
2164                         /* this should not have failed---if it did, report to client */
2165                         if (!W_ERROR_IS_OK(status)) {
2166                                 goto done;
2167                         }
2168                 }
2169         }
2170
2171         status = winreg_del_driver(tmp_ctx, b,
2172                                    info, version);
2173
2174 done:
2175         talloc_free(tmp_ctx);
2176
2177         return status;
2178 }
2179
2180 /****************************************************************
2181  _spoolss_DeletePrinterDriverEx
2182 ****************************************************************/
2183
2184 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2185                                       struct spoolss_DeletePrinterDriverEx *r)
2186 {
2187         struct spoolss_DriverInfo8      *info = NULL;
2188         struct spoolss_DriverInfo8      *info_win2k = NULL;
2189         int                             version;
2190         bool                            delete_files;
2191         WERROR                          status;
2192         struct dcerpc_binding_handle *b;
2193         TALLOC_CTX *tmp_ctx = NULL;
2194
2195         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2196            and not a printer admin, then fail */
2197
2198         if ( (p->session_info->unix_token->uid != sec_initial_uid())
2199                 && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2200                 && !token_contains_name_in_list(
2201                         uidtoname(p->session_info->unix_token->uid),
2202                         p->session_info->info->domain_name,
2203                         NULL,
2204                         p->session_info->security_token, lp_printer_admin(-1)) )
2205         {
2206                 return WERR_ACCESS_DENIED;
2207         }
2208
2209         /* check that we have a valid driver name first */
2210         if ((version = get_version_id(r->in.architecture)) == -1) {
2211                 /* this is what NT returns */
2212                 return WERR_INVALID_ENVIRONMENT;
2213         }
2214
2215         if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) {
2216                 version = r->in.version;
2217         }
2218
2219         tmp_ctx = talloc_new(p->mem_ctx);
2220         if (!tmp_ctx) {
2221                 return WERR_NOMEM;
2222         }
2223
2224         status = winreg_printer_binding_handle(tmp_ctx,
2225                                                get_session_info_system(),
2226                                                p->msg_ctx,
2227                                                &b);
2228         if (!W_ERROR_IS_OK(status)) {
2229                 goto done;
2230         }
2231
2232         status = winreg_get_driver(tmp_ctx, b,
2233                                    r->in.architecture,
2234                                    r->in.driver,
2235                                    version,
2236                                    &info);
2237         if (!W_ERROR_IS_OK(status)) {
2238                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2239
2240                 /*
2241                  * if the client asked for a specific version,
2242                  * or this is something other than Windows NT x86,
2243                  * then we've failed
2244                  */
2245
2246                 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2247                         goto done;
2248
2249                 /* try for Win2k driver if "Windows NT x86" */
2250
2251                 version = 3;
2252                 status = winreg_get_driver(tmp_ctx, b,
2253                                            r->in.architecture,
2254                                            r->in.driver,
2255                                            version, &info);
2256                 if (!W_ERROR_IS_OK(status)) {
2257                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2258                         goto done;
2259                 }
2260         }
2261
2262         if (printer_driver_in_use(tmp_ctx,
2263                                   get_session_info_system(),
2264                                   p->msg_ctx,
2265                                   info)) {
2266                 status = WERR_PRINTER_DRIVER_IN_USE;
2267                 goto done;
2268         }
2269
2270         /*
2271          * we have a couple of cases to consider.
2272          * (1) Are any files in use?  If so and DPD_DELTE_ALL_FILE is set,
2273          *     then the delete should fail if **any** files overlap with
2274          *     other drivers
2275          * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2276          *     non-overlapping files
2277          * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2278          *     is set, the do not delete any files
2279          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2280          */
2281
2282         delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2283
2284         /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2285
2286         if (delete_files &&
2287             (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2288             printer_driver_files_in_use(tmp_ctx,
2289                                         get_session_info_system(),
2290                                         p->msg_ctx,
2291                                         info)) {
2292                 /* no idea of the correct error here */
2293                 status = WERR_ACCESS_DENIED;
2294                 goto done;
2295         }
2296
2297
2298         /* also check for W32X86/3 if necessary; maybe we already have? */
2299
2300         if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION)  ) {
2301                 status = winreg_get_driver(tmp_ctx, b,
2302                                            r->in.architecture,
2303                                            r->in.driver, 3, &info_win2k);
2304                 if (W_ERROR_IS_OK(status)) {
2305
2306                         if (delete_files &&
2307                             (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2308                             printer_driver_files_in_use(info,
2309                                                         get_session_info_system(),
2310                                                         p->msg_ctx,
2311                                                         info_win2k)) {
2312                                 /* no idea of the correct error here */
2313                                 talloc_free(info_win2k);
2314                                 status = WERR_ACCESS_DENIED;
2315                                 goto done;
2316                         }
2317
2318                         /* if we get to here, we now have 2 driver info structures to remove */
2319                         /* remove the Win2k driver first*/
2320
2321                         status = winreg_del_driver(tmp_ctx, b,
2322                                                    info_win2k,
2323                                                    3);
2324
2325                         /* this should not have failed---if it did, report to client */
2326
2327                         if (!W_ERROR_IS_OK(status)) {
2328                                 goto done;
2329                         }
2330
2331                         /*
2332                          * now delete any associated files if delete_files is
2333                          * true. Even if this part failes, we return succes
2334                          * because the driver doesn not exist any more
2335                          */
2336                         if (delete_files) {
2337                                 delete_driver_files(get_session_info_system(),
2338                                                     info_win2k);
2339                         }
2340                 }
2341         }
2342
2343         status = winreg_del_driver(tmp_ctx, b,
2344                                    info,
2345                                    version);
2346         if (!W_ERROR_IS_OK(status)) {
2347                 goto done;
2348         }
2349
2350         /*
2351          * now delete any associated files if delete_files is
2352          * true. Even if this part failes, we return succes
2353          * because the driver doesn not exist any more
2354          */
2355         if (delete_files) {
2356                 delete_driver_files(get_session_info_system(), info);
2357         }
2358
2359 done:
2360         talloc_free(tmp_ctx);
2361         return status;
2362 }
2363
2364
2365 /********************************************************************
2366  GetPrinterData on a printer server Handle.
2367 ********************************************************************/
2368
2369 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2370                                             const char *value,
2371                                             enum winreg_Type *type,
2372                                             union spoolss_PrinterData *data)
2373 {
2374         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2375
2376         if (!strcasecmp_m(value, "W3SvcInstalled")) {
2377                 *type = REG_DWORD;
2378                 data->value = 0x00;
2379                 return WERR_OK;
2380         }
2381
2382         if (!strcasecmp_m(value, "BeepEnabled")) {
2383                 *type = REG_DWORD;
2384                 data->value = 0x00;
2385                 return WERR_OK;
2386         }
2387
2388         if (!strcasecmp_m(value, "EventLog")) {
2389                 *type = REG_DWORD;
2390                 /* formally was 0x1b */
2391                 data->value = 0x00;
2392                 return WERR_OK;
2393         }
2394
2395         if (!strcasecmp_m(value, "NetPopup")) {
2396                 *type = REG_DWORD;
2397                 data->value = 0x00;
2398                 return WERR_OK;
2399         }
2400
2401         if (!strcasecmp_m(value, "MajorVersion")) {
2402                 *type = REG_DWORD;
2403
2404                 /* Windows NT 4.0 seems to not allow uploading of drivers
2405                    to a server that reports 0x3 as the MajorVersion.
2406                    need to investigate more how Win2k gets around this .
2407                    -- jerry */
2408
2409                 if (RA_WINNT == get_remote_arch()) {
2410                         data->value = 0x02;
2411                 } else {
2412                         data->value = 0x03;
2413                 }
2414
2415                 return WERR_OK;
2416         }
2417
2418         if (!strcasecmp_m(value, "MinorVersion")) {
2419                 *type = REG_DWORD;
2420                 data->value = 0x00;
2421                 return WERR_OK;
2422         }
2423
2424         /* REG_BINARY
2425          *  uint32_t size        = 0x114
2426          *  uint32_t major       = 5
2427          *  uint32_t minor       = [0|1]
2428          *  uint32_t build       = [2195|2600]
2429          *  extra unicode string = e.g. "Service Pack 3"
2430          */
2431         if (!strcasecmp_m(value, "OSVersion")) {
2432                 DATA_BLOB blob;
2433                 enum ndr_err_code ndr_err;
2434                 struct spoolss_OSVersion os;
2435
2436                 os.major                = 5;    /* Windows 2000 == 5.0 */
2437                 os.minor                = 0;
2438                 os.build                = 2195; /* build */
2439                 os.extra_string         = "";   /* leave extra string empty */
2440
2441                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2442                         (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2443                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2444                         return WERR_GENERAL_FAILURE;
2445                 }
2446
2447                 *type = REG_BINARY;
2448                 data->binary = blob;
2449
2450                 return WERR_OK;
2451         }
2452
2453
2454         if (!strcasecmp_m(value, "DefaultSpoolDirectory")) {
2455                 *type = REG_SZ;
2456
2457                 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2458                 W_ERROR_HAVE_NO_MEMORY(data->string);
2459
2460                 return WERR_OK;
2461         }
2462
2463         if (!strcasecmp_m(value, "Architecture")) {
2464                 *type = REG_SZ;
2465                 data->string = talloc_strdup(mem_ctx,
2466                         lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2467                 W_ERROR_HAVE_NO_MEMORY(data->string);
2468
2469                 return WERR_OK;
2470         }
2471
2472         if (!strcasecmp_m(value, "DsPresent")) {
2473                 *type = REG_DWORD;
2474
2475                 /* only show the publish check box if we are a
2476                    member of a AD domain */
2477
2478                 if (lp_security() == SEC_ADS) {
2479                         data->value = 0x01;
2480                 } else {
2481                         data->value = 0x00;
2482                 }
2483                 return WERR_OK;
2484         }
2485
2486         if (!strcasecmp_m(value, "DNSMachineName")) {
2487                 const char *hostname = get_mydnsfullname();
2488
2489                 if (!hostname) {
2490                         return WERR_BADFILE;
2491                 }
2492
2493                 *type = REG_SZ;
2494                 data->string = talloc_strdup(mem_ctx, hostname);
2495                 W_ERROR_HAVE_NO_MEMORY(data->string);
2496
2497                 return WERR_OK;
2498         }
2499
2500         *type = REG_NONE;
2501
2502         return WERR_INVALID_PARAM;
2503 }
2504
2505 /****************************************************************
2506  _spoolss_GetPrinterData
2507 ****************************************************************/
2508
2509 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2510                                struct spoolss_GetPrinterData *r)
2511 {
2512         struct spoolss_GetPrinterDataEx r2;
2513
2514         r2.in.handle            = r->in.handle;
2515         r2.in.key_name          = "PrinterDriverData";
2516         r2.in.value_name        = r->in.value_name;
2517         r2.in.offered           = r->in.offered;
2518         r2.out.type             = r->out.type;
2519         r2.out.data             = r->out.data;
2520         r2.out.needed           = r->out.needed;
2521
2522         return _spoolss_GetPrinterDataEx(p, &r2);
2523 }
2524
2525 /*********************************************************
2526  Connect to the client machine.
2527 **********************************************************/
2528
2529 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2530                         struct sockaddr_storage *client_ss, const char *remote_machine)
2531 {
2532         NTSTATUS ret;
2533         struct cli_state *the_cli;
2534         struct sockaddr_storage rm_addr;
2535         char addr[INET6_ADDRSTRLEN];
2536
2537         if ( is_zero_addr(client_ss) ) {
2538                 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2539                         remote_machine));
2540                 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2541                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2542                         return false;
2543                 }
2544                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2545         } else {
2546                 rm_addr = *client_ss;
2547                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2548                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2549                         addr));
2550         }
2551
2552         if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2553                 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2554                         addr));
2555                 return false;
2556         }
2557
2558         /* setup the connection */
2559         ret = cli_full_connection( &the_cli, lp_netbios_name(), remote_machine,
2560                 &rm_addr, 0, "IPC$", "IPC",
2561                 "", /* username */
2562                 "", /* domain */
2563                 "", /* password */
2564                 0, lp_client_signing());
2565
2566         if ( !NT_STATUS_IS_OK( ret ) ) {
2567                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2568                         remote_machine ));
2569                 return false;
2570         }
2571
2572         if ( the_cli->protocol != PROTOCOL_NT1 ) {
2573                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2574                 cli_shutdown(the_cli);
2575                 return false;
2576         }
2577
2578         /*
2579          * Ok - we have an anonymous connection to the IPC$ share.
2580          * Now start the NT Domain stuff :-).
2581          */
2582
2583         ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2584         if (!NT_STATUS_IS_OK(ret)) {
2585                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2586                         remote_machine, nt_errstr(ret)));
2587                 cli_shutdown(the_cli);
2588                 return false;
2589         }
2590
2591         return true;
2592 }
2593
2594 /***************************************************************************
2595  Connect to the client.
2596 ****************************************************************************/
2597
2598 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2599                                         uint32_t localprinter,
2600                                         enum winreg_Type type,
2601                                         struct policy_handle *handle,
2602                                         struct notify_back_channel **_chan,
2603                                         struct sockaddr_storage *client_ss,
2604                                         struct messaging_context *msg_ctx)
2605 {
2606         WERROR result;
2607         NTSTATUS status;
2608         struct notify_back_channel *chan;
2609
2610         for (chan = back_channels; chan; chan = chan->next) {
2611                 if (memcmp(&chan->client_address, client_ss,
2612                            sizeof(struct sockaddr_storage)) == 0) {
2613                         break;
2614                 }
2615         }
2616
2617         /*
2618          * If it's the first connection, contact the client
2619          * and connect to the IPC$ share anonymously
2620          */
2621         if (!chan) {
2622                 fstring unix_printer;
2623
2624                 /* the +2 is to strip the leading 2 backslashs */
2625                 fstrcpy(unix_printer, printer + 2);
2626
2627                 chan = talloc_zero(back_channels, struct notify_back_channel);
2628                 if (!chan) {
2629                         return false;
2630                 }
2631                 chan->client_address = *client_ss;
2632
2633                 if (!spoolss_connect_to_client(&chan->cli_pipe, client_ss, unix_printer)) {
2634                         TALLOC_FREE(chan);
2635                         return false;
2636                 }
2637                 chan->binding_handle = chan->cli_pipe->binding_handle;
2638
2639                 DLIST_ADD(back_channels, chan);
2640
2641                 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2642                                    receive_notify2_message_list);
2643                 /* Tell the connections db we're now interested in printer
2644                  * notify messages. */
2645                 serverid_register_msg_flags(messaging_server_id(msg_ctx),
2646                                             true, FLAG_MSG_PRINT_NOTIFY);
2647         }
2648
2649         /*
2650          * Tell the specific printing tdb we want messages for this printer
2651          * by registering our PID.
2652          */
2653
2654         if (!print_notify_register_pid(snum)) {
2655                 DEBUG(0, ("Failed to register our pid for printer %s\n",
2656                           printer));
2657         }
2658
2659         status = dcerpc_spoolss_ReplyOpenPrinter(chan->binding_handle,
2660                                                  talloc_tos(),
2661                                                  printer,
2662                                                  localprinter,
2663                                                  type,
2664                                                  0,
2665                                                  NULL,
2666                                                  handle,
2667                                                  &result);
2668         if (!NT_STATUS_IS_OK(status)) {
2669                 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2670                 result = ntstatus_to_werror(status);
2671         } else if (!W_ERROR_IS_OK(result)) {
2672                 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2673         }
2674
2675         chan->active_connections++;
2676         *_chan = chan;
2677
2678         return (W_ERROR_IS_OK(result));
2679 }
2680
2681 /****************************************************************
2682  ****************************************************************/
2683
2684 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2685                                                              const struct spoolss_NotifyOption *r)
2686 {
2687         struct spoolss_NotifyOption *option;
2688         uint32_t i,k;
2689
2690         if (!r) {
2691                 return NULL;
2692         }
2693
2694         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2695         if (!option) {
2696                 return NULL;
2697         }
2698
2699         *option = *r;
2700
2701         if (!option->count) {
2702                 return option;
2703         }
2704
2705         option->types = talloc_zero_array(option,
2706                 struct spoolss_NotifyOptionType, option->count);
2707         if (!option->types) {
2708                 talloc_free(option);
2709                 return NULL;
2710         }
2711
2712         for (i=0; i < option->count; i++) {
2713                 option->types[i] = r->types[i];
2714
2715                 if (option->types[i].count) {
2716                         option->types[i].fields = talloc_zero_array(option,
2717                                 union spoolss_Field, option->types[i].count);
2718                         if (!option->types[i].fields) {
2719                                 talloc_free(option);
2720                                 return NULL;
2721                         }
2722                         for (k=0; k<option->types[i].count; k++) {
2723                                 option->types[i].fields[k] =
2724                                         r->types[i].fields[k];
2725                         }
2726                 }
2727         }
2728
2729         return option;
2730 }
2731
2732 /****************************************************************
2733  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2734  *
2735  * before replying OK: status=0 a rpc call is made to the workstation
2736  * asking ReplyOpenPrinter
2737  *
2738  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2739  * called from api_spoolss_rffpcnex
2740 ****************************************************************/
2741
2742 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2743                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2744 {
2745         int snum = -1;
2746         struct spoolss_NotifyOption *option = r->in.notify_options;
2747         struct sockaddr_storage client_ss;
2748         socklen_t client_len;
2749
2750         /* store the notify value in the printer struct */
2751
2752         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2753
2754         if (!Printer) {
2755                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2756                         "Invalid handle (%s:%u:%u).\n",
2757                         OUR_HANDLE(r->in.handle)));
2758                 return WERR_BADFID;
2759         }
2760
2761         Printer->notify.flags           = r->in.flags;
2762         Printer->notify.options         = r->in.options;
2763         Printer->notify.printerlocal    = r->in.printer_local;
2764         Printer->notify.msg_ctx         = p->msg_ctx;
2765
2766         TALLOC_FREE(Printer->notify.option);
2767         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2768
2769         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2770
2771         /* Connect to the client machine and send a ReplyOpenPrinter */
2772
2773         if ( Printer->printer_type == SPLHND_SERVER)
2774                 snum = -1;
2775         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2776                         !get_printer_snum(p, r->in.handle, &snum, NULL) )
2777                 return WERR_BADFID;
2778
2779         DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2780                   "remote_address is %s\n",
2781                   tsocket_address_string(p->remote_address, p->mem_ctx)));
2782
2783         if (!lp_print_notify_backchannel(snum)) {
2784                 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2785                         "backchannel disabled\n"));
2786                 return WERR_SERVER_UNAVAILABLE;
2787         }
2788
2789         client_len = tsocket_address_bsd_sockaddr(p->remote_address,
2790                                                   (struct sockaddr *) &client_ss,
2791                                                   sizeof(struct sockaddr_storage));
2792         if (client_len < 0) {
2793                 return WERR_NOMEM;
2794         }
2795
2796         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2797                                         Printer->notify.printerlocal, REG_SZ,
2798                                         &Printer->notify.cli_hnd,
2799                                         &Printer->notify.cli_chan,
2800                                         &client_ss, p->msg_ctx)) {
2801                 return WERR_SERVER_UNAVAILABLE;
2802         }
2803
2804         return WERR_OK;
2805 }
2806
2807 /*******************************************************************
2808  * fill a notify_info_data with the servername
2809  ********************************************************************/
2810
2811 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2812                                        int snum,
2813                                        struct spoolss_Notify *data,
2814                                        print_queue_struct *queue,
2815                                        struct spoolss_PrinterInfo2 *pinfo2,
2816                                        TALLOC_CTX *mem_ctx)
2817 {
2818         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2819 }
2820
2821 /*******************************************************************
2822  * fill a notify_info_data with the printername (not including the servername).
2823  ********************************************************************/
2824
2825 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2826                                         int snum,
2827                                         struct spoolss_Notify *data,
2828                                         print_queue_struct *queue,
2829                                         struct spoolss_PrinterInfo2 *pinfo2,
2830                                         TALLOC_CTX *mem_ctx)
2831 {
2832         /* the notify name should not contain the \\server\ part */
2833         const char *p = strrchr(pinfo2->printername, '\\');
2834
2835         if (!p) {
2836                 p = pinfo2->printername;
2837         } else {
2838                 p++;
2839         }
2840
2841         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2842 }
2843
2844 /*******************************************************************
2845  * fill a notify_info_data with the servicename
2846  ********************************************************************/
2847
2848 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2849                                       int snum,
2850                                       struct spoolss_Notify *data,
2851                                       print_queue_struct *queue,
2852                                       struct spoolss_PrinterInfo2 *pinfo2,
2853                                       TALLOC_CTX *mem_ctx)
2854 {
2855         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2856 }
2857
2858 /*******************************************************************
2859  * fill a notify_info_data with the port name
2860  ********************************************************************/
2861
2862 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2863                                      int snum,
2864                                      struct spoolss_Notify *data,
2865                                      print_queue_struct *queue,
2866                                      struct spoolss_PrinterInfo2 *pinfo2,
2867                                      TALLOC_CTX *mem_ctx)
2868 {
2869         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2870 }
2871
2872 /*******************************************************************
2873  * fill a notify_info_data with the printername
2874  * but it doesn't exist, have to see what to do
2875  ********************************************************************/
2876
2877 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2878                                        int snum,
2879                                        struct spoolss_Notify *data,
2880                                        print_queue_struct *queue,
2881                                        struct spoolss_PrinterInfo2 *pinfo2,
2882                                        TALLOC_CTX *mem_ctx)
2883 {
2884         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2885 }
2886
2887 /*******************************************************************
2888  * fill a notify_info_data with the comment
2889  ********************************************************************/
2890
2891 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2892                                    int snum,
2893                                    struct spoolss_Notify *data,
2894                                    print_queue_struct *queue,
2895                                    struct spoolss_PrinterInfo2 *pinfo2,
2896                                    TALLOC_CTX *mem_ctx)
2897 {
2898         const char *p;
2899
2900         if (*pinfo2->comment == '\0') {
2901                 p = lp_comment(snum);
2902         } else {
2903                 p = pinfo2->comment;
2904         }
2905
2906         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2907 }
2908
2909 /*******************************************************************
2910  * fill a notify_info_data with the comment
2911  * location = "Room 1, floor 2, building 3"
2912  ********************************************************************/
2913
2914 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2915                                     int snum,
2916                                     struct spoolss_Notify *data,
2917                                     print_queue_struct *queue,
2918                                     struct spoolss_PrinterInfo2 *pinfo2,
2919                                     TALLOC_CTX *mem_ctx)
2920 {
2921         const char *loc = pinfo2->location;
2922         NTSTATUS status;
2923
2924         status = printer_list_get_printer(mem_ctx,
2925                                           pinfo2->sharename,
2926                                           NULL,
2927                                           &loc,
2928                                           NULL);
2929         if (NT_STATUS_IS_OK(status)) {
2930                 if (loc == NULL) {
2931                         loc = pinfo2->location;
2932                 }
2933         }
2934
2935         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, loc);
2936 }
2937
2938 /*******************************************************************
2939  * fill a notify_info_data with the device mode
2940  * jfm:xxxx don't to it for know but that's a real problem !!!
2941  ********************************************************************/
2942
2943 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2944                                    int snum,
2945                                    struct spoolss_Notify *data,
2946                                    print_queue_struct *queue,
2947                                    struct spoolss_PrinterInfo2 *pinfo2,
2948                                    TALLOC_CTX *mem_ctx)
2949 {
2950         /* for a dummy implementation we have to zero the fields */
2951         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2952 }
2953
2954 /*******************************************************************
2955  * fill a notify_info_data with the separator file name
2956  ********************************************************************/
2957
2958 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2959                                    int snum,
2960                                    struct spoolss_Notify *data,
2961                                    print_queue_struct *queue,
2962                                    struct spoolss_PrinterInfo2 *pinfo2,
2963                                    TALLOC_CTX *mem_ctx)
2964 {
2965         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2966 }
2967
2968 /*******************************************************************
2969  * fill a notify_info_data with the print processor
2970  * jfm:xxxx return always winprint to indicate we don't do anything to it
2971  ********************************************************************/
2972
2973 static void spoolss_notify_print_processor(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)
2979 {
2980         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2981 }
2982
2983 /*******************************************************************
2984  * fill a notify_info_data with the print processor options
2985  * jfm:xxxx send an empty string
2986  ********************************************************************/
2987
2988 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2989                                       int snum,
2990                                       struct spoolss_Notify *data,
2991                                       print_queue_struct *queue,
2992                                       struct spoolss_PrinterInfo2 *pinfo2,
2993                                       TALLOC_CTX *mem_ctx)
2994 {
2995         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2996 }
2997
2998 /*******************************************************************
2999  * fill a notify_info_data with the data type
3000  * jfm:xxxx always send RAW as data type
3001  ********************************************************************/
3002
3003 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
3004                                     int snum,
3005                                     struct spoolss_Notify *data,
3006                                     print_queue_struct *queue,
3007                                     struct spoolss_PrinterInfo2 *pinfo2,
3008                                     TALLOC_CTX *mem_ctx)
3009 {
3010         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
3011 }
3012
3013 /*******************************************************************
3014  * fill a notify_info_data with the security descriptor
3015  * jfm:xxxx send an null pointer to say no security desc
3016  * have to implement security before !
3017  ********************************************************************/
3018
3019 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
3020                                          int snum,
3021                                          struct spoolss_Notify *data,
3022                                          print_queue_struct *queue,
3023                                          struct spoolss_PrinterInfo2 *pinfo2,
3024                                          TALLOC_CTX *mem_ctx)
3025 {
3026         SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
3027 }
3028
3029 /*******************************************************************
3030  * fill a notify_info_data with the attributes
3031  * jfm:xxxx a samba printer is always shared
3032  ********************************************************************/
3033
3034 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
3035                                       int snum,
3036                                       struct spoolss_Notify *data,
3037                                       print_queue_struct *queue,
3038                                       struct spoolss_PrinterInfo2 *pinfo2,
3039                                       TALLOC_CTX *mem_ctx)
3040 {
3041         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
3042 }
3043
3044 /*******************************************************************
3045  * fill a notify_info_data with the priority
3046  ********************************************************************/
3047
3048 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
3049                                     int snum,
3050                                     struct spoolss_Notify *data,
3051                                     print_queue_struct *queue,
3052                                     struct spoolss_PrinterInfo2 *pinfo2,
3053                                     TALLOC_CTX *mem_ctx)
3054 {
3055         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
3056 }
3057
3058 /*******************************************************************
3059  * fill a notify_info_data with the default priority
3060  ********************************************************************/
3061
3062 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
3063                                             int snum,
3064                                             struct spoolss_Notify *data,
3065                                             print_queue_struct *queue,
3066                                             struct spoolss_PrinterInfo2 *pinfo2,
3067                                             TALLOC_CTX *mem_ctx)
3068 {
3069         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
3070 }
3071
3072 /*******************************************************************
3073  * fill a notify_info_data with the start time
3074  ********************************************************************/
3075
3076 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
3077                                       int snum,
3078                                       struct spoolss_Notify *data,
3079                                       print_queue_struct *queue,
3080                                       struct spoolss_PrinterInfo2 *pinfo2,
3081                                       TALLOC_CTX *mem_ctx)
3082 {
3083         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3084 }
3085
3086 /*******************************************************************
3087  * fill a notify_info_data with the until time
3088  ********************************************************************/
3089
3090 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3091                                       int snum,
3092                                       struct spoolss_Notify *data,
3093                                       print_queue_struct *queue,
3094                                       struct spoolss_PrinterInfo2 *pinfo2,
3095                                       TALLOC_CTX *mem_ctx)
3096 {
3097         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3098 }
3099
3100 /*******************************************************************
3101  * fill a notify_info_data with the status
3102  ********************************************************************/
3103
3104 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3105                                   int snum,
3106                                   struct spoolss_Notify *data,
3107                                   print_queue_struct *queue,
3108                                   struct spoolss_PrinterInfo2 *pinfo2,
3109                                   TALLOC_CTX *mem_ctx)
3110 {
3111         print_status_struct status;
3112
3113         print_queue_length(msg_ctx, snum, &status);
3114         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3115 }
3116
3117 /*******************************************************************
3118  * fill a notify_info_data with the number of jobs queued
3119  ********************************************************************/
3120
3121 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3122                                  int snum,
3123                                  struct spoolss_Notify *data,
3124                                  print_queue_struct *queue,
3125                                  struct spoolss_PrinterInfo2 *pinfo2,
3126                                  TALLOC_CTX *mem_ctx)
3127 {
3128         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3129                 data, print_queue_length(msg_ctx, snum, NULL));
3130 }
3131
3132 /*******************************************************************
3133  * fill a notify_info_data with the average ppm
3134  ********************************************************************/
3135
3136 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3137                                        int snum,
3138                                        struct spoolss_Notify *data,
3139                                        print_queue_struct *queue,
3140                                        struct spoolss_PrinterInfo2 *pinfo2,
3141                                        TALLOC_CTX *mem_ctx)
3142 {
3143         /* always respond 8 pages per minutes */
3144         /* a little hard ! */
3145         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3146 }
3147
3148 /*******************************************************************
3149  * fill a notify_info_data with username
3150  ********************************************************************/
3151
3152 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3153                                     int snum,
3154                                     struct spoolss_Notify *data,
3155                                     print_queue_struct *queue,
3156                                     struct spoolss_PrinterInfo2 *pinfo2,
3157                                     TALLOC_CTX *mem_ctx)
3158 {
3159         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3160 }
3161
3162 /*******************************************************************
3163  * fill a notify_info_data with job status
3164  ********************************************************************/
3165
3166 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3167                                       int snum,
3168                                       struct spoolss_Notify *data,
3169                                       print_queue_struct *queue,
3170                                       struct spoolss_PrinterInfo2 *pinfo2,
3171                                       TALLOC_CTX *mem_ctx)
3172 {
3173         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3174 }
3175
3176 /*******************************************************************
3177  * fill a notify_info_data with job name
3178  ********************************************************************/
3179
3180 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3181                                     int snum,
3182                                     struct spoolss_Notify *data,
3183                                     print_queue_struct *queue,
3184                                     struct spoolss_PrinterInfo2 *pinfo2,
3185                                     TALLOC_CTX *mem_ctx)
3186 {
3187         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3188 }
3189
3190 /*******************************************************************
3191  * fill a notify_info_data with job status
3192  ********************************************************************/
3193
3194 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3195                                              int snum,
3196                                              struct spoolss_Notify *data,
3197                                              print_queue_struct *queue,
3198                                              struct spoolss_PrinterInfo2 *pinfo2,
3199                                              TALLOC_CTX *mem_ctx)
3200 {
3201         /*
3202          * Now we're returning job status codes we just return a "" here. JRA.
3203          */
3204
3205         const char *p = "";
3206
3207 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3208         p = "unknown";
3209
3210         switch (queue->status) {
3211         case LPQ_QUEUED:
3212                 p = "Queued";
3213                 break;
3214         case LPQ_PAUSED:
3215                 p = "";    /* NT provides the paused string */
3216                 break;
3217         case LPQ_SPOOLING:
3218                 p = "Spooling";
3219                 break;
3220         case LPQ_PRINTING:
3221                 p = "Printing";
3222                 break;
3223         }
3224 #endif /* NO LONGER NEEDED. */
3225
3226         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3227 }
3228
3229 /*******************************************************************
3230  * fill a notify_info_data with job time
3231  ********************************************************************/
3232
3233 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3234                                     int snum,
3235                                     struct spoolss_Notify *data,
3236                                     print_queue_struct *queue,
3237                                     struct spoolss_PrinterInfo2 *pinfo2,
3238                                     TALLOC_CTX *mem_ctx)
3239 {
3240         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3241 }
3242
3243 /*******************************************************************
3244  * fill a notify_info_data with job size
3245  ********************************************************************/
3246
3247 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3248                                     int snum,
3249                                     struct spoolss_Notify *data,
3250                                     print_queue_struct *queue,
3251                                     struct spoolss_PrinterInfo2 *pinfo2,
3252                                     TALLOC_CTX *mem_ctx)
3253 {
3254         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3255 }
3256
3257 /*******************************************************************
3258  * fill a notify_info_data with page info
3259  ********************************************************************/
3260 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3261                                        int snum,
3262                                 struct spoolss_Notify *data,
3263                                 print_queue_struct *queue,
3264                                 struct spoolss_PrinterInfo2 *pinfo2,
3265                                 TALLOC_CTX *mem_ctx)
3266 {
3267         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3268 }
3269
3270 /*******************************************************************
3271  * fill a notify_info_data with pages printed info.
3272  ********************************************************************/
3273 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3274                                          int snum,
3275                                 struct spoolss_Notify *data,
3276                                 print_queue_struct *queue,
3277                                 struct spoolss_PrinterInfo2 *pinfo2,
3278                                 TALLOC_CTX *mem_ctx)
3279 {
3280         /* Add code when back-end tracks this */
3281         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3282 }
3283
3284 /*******************************************************************
3285  Fill a notify_info_data with job position.
3286  ********************************************************************/
3287
3288 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3289                                         int snum,
3290                                         struct spoolss_Notify *data,
3291                                         print_queue_struct *queue,
3292                                         struct spoolss_PrinterInfo2 *pinfo2,
3293                                         TALLOC_CTX *mem_ctx)
3294 {
3295         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3296 }
3297
3298 /*******************************************************************
3299  Fill a notify_info_data with submitted time.
3300  ********************************************************************/
3301
3302 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3303                                           int snum,
3304                                           struct spoolss_Notify *data,
3305                                           print_queue_struct *queue,
3306                                           struct spoolss_PrinterInfo2 *pinfo2,
3307                                           TALLOC_CTX *mem_ctx)
3308 {
3309         data->data.string.string = NULL;
3310         data->data.string.size = 0;
3311
3312         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3313                                &data->data.string.string,
3314                                &data->data.string.size);
3315
3316 }
3317
3318 struct s_notify_info_data_table
3319 {
3320         enum spoolss_NotifyType type;
3321         uint16_t field;
3322         const char *name;
3323         enum spoolss_NotifyTable variable_type;
3324         void (*fn) (struct messaging_context *msg_ctx,
3325                     int snum, struct spoolss_Notify *data,
3326                     print_queue_struct *queue,
3327                     struct spoolss_PrinterInfo2 *pinfo2,
3328                     TALLOC_CTX *mem_ctx);
3329 };
3330
3331 /* A table describing the various print notification constants and
3332    whether the notification data is a pointer to a variable sized
3333    buffer, a one value uint32_t or a two value uint32_t. */
3334
3335 static const struct s_notify_info_data_table notify_info_data_table[] =
3336 {
3337 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME,         "PRINTER_NOTIFY_FIELD_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3338 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME,        "PRINTER_NOTIFY_FIELD_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3339 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME,          "PRINTER_NOTIFY_FIELD_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
3340 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME,           "PRINTER_NOTIFY_FIELD_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3341 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME,         "PRINTER_NOTIFY_FIELD_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3342 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT,             "PRINTER_NOTIFY_FIELD_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
3343 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION,            "PRINTER_NOTIFY_FIELD_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
3344 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE,             "PRINTER_NOTIFY_FIELD_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3345 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE,             "PRINTER_NOTIFY_FIELD_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
3346 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR,     "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3347 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS,          "PRINTER_NOTIFY_FIELD_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3348 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE,            "PRINTER_NOTIFY_FIELD_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3349 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
3350 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES,          "PRINTER_NOTIFY_FIELD_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
3351 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY,            "PRINTER_NOTIFY_FIELD_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3352 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
3353 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME,          "PRINTER_NOTIFY_FIELD_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3354 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME,          "PRINTER_NOTIFY_FIELD_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3355 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS,              "PRINTER_NOTIFY_FIELD_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
3356 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING,       "PRINTER_NOTIFY_FIELD_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
3357 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS,               "PRINTER_NOTIFY_FIELD_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
3358 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM,         "PRINTER_NOTIFY_FIELD_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
3359 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES,         "PRINTER_NOTIFY_FIELD_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
3360 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED,       "PRINTER_NOTIFY_FIELD_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3361 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES,         "PRINTER_NOTIFY_FIELD_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
3362 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED,       "PRINTER_NOTIFY_FIELD_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3363 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINTER_NAME,            "JOB_NOTIFY_FIELD_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3364 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_MACHINE_NAME,            "JOB_NOTIFY_FIELD_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3365 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PORT_NAME,               "JOB_NOTIFY_FIELD_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3366 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_USER_NAME,               "JOB_NOTIFY_FIELD_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
3367 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_NOTIFY_NAME,             "JOB_NOTIFY_FIELD_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
3368 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DATATYPE,                "JOB_NOTIFY_FIELD_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3369 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINT_PROCESSOR,         "JOB_NOTIFY_FIELD_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3370 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PARAMETERS,              "JOB_NOTIFY_FIELD_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3371 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DRIVER_NAME,             "JOB_NOTIFY_FIELD_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3372 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DEVMODE,                 "JOB_NOTIFY_FIELD_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3373 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS,                  "JOB_NOTIFY_FIELD_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
3374 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS_STRING,           "JOB_NOTIFY_FIELD_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
3375 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
3376 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DOCUMENT,                "JOB_NOTIFY_FIELD_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
3377 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRIORITY,                "JOB_NOTIFY_FIELD_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3378 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_POSITION,                "JOB_NOTIFY_FIELD_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
3379 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SUBMITTED,               "JOB_NOTIFY_FIELD_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
3380 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_START_TIME,              "JOB_NOTIFY_FIELD_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3381 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_UNTIL_TIME,              "JOB_NOTIFY_FIELD_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3382 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TIME,                    "JOB_NOTIFY_FIELD_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
3383 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_PAGES,             "JOB_NOTIFY_FIELD_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
3384 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PAGES_PRINTED,           "JOB_NOTIFY_FIELD_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
3385 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_BYTES,             "JOB_NOTIFY_FIELD_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
3386 };
3387
3388 /*******************************************************************
3389  Return the variable_type of info_data structure.
3390 ********************************************************************/
3391
3392 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3393                                                                   uint16_t field)
3394 {
3395         int i=0;
3396
3397         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3398                 if ( (notify_info_data_table[i].type == type) &&
3399                      (notify_info_data_table[i].field == field) ) {
3400                         return notify_info_data_table[i].variable_type;
3401                 }
3402         }
3403
3404         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3405
3406         return (enum spoolss_NotifyTable) 0;
3407 }
3408
3409 /****************************************************************************
3410 ****************************************************************************/
3411
3412 static bool search_notify(enum spoolss_NotifyType type,
3413                           uint16_t field,
3414                           int *value)
3415 {
3416         int i;
3417
3418         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3419                 if (notify_info_data_table[i].type == type &&
3420                     notify_info_data_table[i].field == field &&
3421                     notify_info_data_table[i].fn != NULL) {
3422                         *value = i;
3423                         return true;
3424                 }
3425         }
3426
3427         return false;
3428 }
3429
3430 /****************************************************************************
3431 ****************************************************************************/
3432
3433 static void construct_info_data(struct spoolss_Notify *info_data,
3434                                 enum spoolss_NotifyType type,
3435                                 uint16_t field, int id)
3436 {
3437         info_data->type                 = type;
3438         info_data->field.field          = field;
3439         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3440         info_data->job_id               = id;
3441 }
3442
3443 /*******************************************************************
3444  *
3445  * fill a notify_info struct with info asked
3446  *
3447  ********************************************************************/
3448
3449 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3450                                           struct printer_handle *print_hnd,
3451                                           struct spoolss_NotifyInfo *info,
3452                                           struct spoolss_PrinterInfo2 *pinfo2,
3453                                           int snum,
3454                                           const struct spoolss_NotifyOptionType *option_type,
3455                                           uint32_t id,
3456                                           TALLOC_CTX *mem_ctx)
3457 {
3458         int field_num,j;
3459         enum spoolss_NotifyType type;
3460         uint16_t field;
3461
3462         struct spoolss_Notify *current_data;
3463
3464         type = option_type->type;
3465
3466         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3467                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3468                 option_type->count, lp_servicename(snum)));
3469
3470         for(field_num=0; field_num < option_type->count; field_num++) {
3471                 field = option_type->fields[field_num].field;
3472
3473                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3474
3475                 if (!search_notify(type, field, &j) )
3476                         continue;
3477
3478                 info->notifies = talloc_realloc(info, info->notifies,
3479                                                       struct spoolss_Notify,
3480                                                       info->count + 1);
3481                 if (info->notifies == NULL) {
3482                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3483                         return false;
3484                 }
3485
3486                 current_data = &info->notifies[info->count];
3487
3488                 construct_info_data(current_data, type, field, id);
3489
3490                 DEBUG(10, ("construct_notify_printer_info: "
3491                            "calling [%s]  snum=%d  printername=[%s])\n",
3492                            notify_info_data_table[j].name, snum,
3493                            pinfo2->printername));
3494
3495                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3496                                              NULL, pinfo2, mem_ctx);
3497
3498                 info->count++;
3499         }
3500
3501         return true;
3502 }
3503
3504 /*******************************************************************
3505  *
3506  * fill a notify_info struct with info asked
3507  *
3508  ********************************************************************/
3509
3510 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3511                                        print_queue_struct *queue,
3512                                        struct spoolss_NotifyInfo *info,
3513                                        struct spoolss_PrinterInfo2 *pinfo2,
3514                                        int snum,
3515                                        const struct spoolss_NotifyOptionType *option_type,
3516                                        uint32_t id,
3517                                        TALLOC_CTX *mem_ctx)
3518 {
3519         int field_num,j;
3520         enum spoolss_NotifyType type;
3521         uint16_t field;
3522         struct spoolss_Notify *current_data;
3523
3524         DEBUG(4,("construct_notify_jobs_info\n"));
3525
3526         type = option_type->type;
3527
3528         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3529                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3530                 option_type->count));
3531
3532         for(field_num=0; field_num<option_type->count; field_num++) {
3533                 field = option_type->fields[field_num].field;
3534
3535                 if (!search_notify(type, field, &j) )
3536                         continue;
3537
3538                 info->notifies = talloc_realloc(info, info->notifies,
3539                                                       struct spoolss_Notify,
3540                                                       info->count + 1);
3541                 if (info->notifies == NULL) {
3542                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3543                         return false;
3544                 }
3545
3546                 current_data=&(info->notifies[info->count]);
3547
3548                 construct_info_data(current_data, type, field, id);
3549                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3550                                              queue, pinfo2, mem_ctx);
3551                 info->count++;
3552         }
3553
3554         return true;
3555 }
3556
3557 /*
3558  * JFM: The enumeration is not that simple, it's even non obvious.
3559  *
3560  * let's take an example: I want to monitor the PRINTER SERVER for
3561  * the printer's name and the number of jobs currently queued.
3562  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3563  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3564  *
3565  * I have 3 printers on the back of my server.
3566  *
3567  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3568  * structures.
3569  *   Number     Data                    Id
3570  *      1       printer 1 name          1
3571  *      2       printer 1 cjob          1
3572  *      3       printer 2 name          2
3573  *      4       printer 2 cjob          2
3574  *      5       printer 3 name          3
3575  *      6       printer 3 name          3
3576  *
3577  * that's the print server case, the printer case is even worse.
3578  */
3579
3580 /*******************************************************************
3581  *
3582  * enumerate all printers on the printserver
3583  * fill a notify_info struct with info asked
3584  *
3585  ********************************************************************/
3586
3587 static WERROR printserver_notify_info(struct pipes_struct *p,
3588                                       struct policy_handle *hnd,
3589                                       struct spoolss_NotifyInfo *info,
3590                                       TALLOC_CTX *mem_ctx)
3591 {
3592         int snum;
3593         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3594         int n_services=lp_numservices();
3595         int i;
3596         struct spoolss_NotifyOption *option;
3597         struct spoolss_NotifyOptionType option_type;
3598         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3599         WERROR result;
3600
3601         DEBUG(4,("printserver_notify_info\n"));
3602
3603         if (!Printer)
3604                 return WERR_BADFID;
3605
3606         option = Printer->notify.option;
3607
3608         info->version   = 2;
3609         info->notifies  = NULL;
3610         info->count     = 0;
3611
3612         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3613            sending a ffpcn() request first */
3614
3615         if ( !option )
3616                 return WERR_BADFID;
3617
3618         for (i=0; i<option->count; i++) {
3619                 option_type = option->types[i];
3620
3621                 if (option_type.type != PRINTER_NOTIFY_TYPE)
3622                         continue;
3623
3624                 for (snum = 0; snum < n_services; snum++) {
3625                         if (!lp_browseable(snum) ||
3626                             !lp_snum_ok(snum) ||
3627                             !lp_print_ok(snum)) {
3628                                 continue; /* skip */
3629                         }
3630
3631                         /* Maybe we should use the SYSTEM session_info here... */
3632                         result = winreg_get_printer_internal(mem_ctx,
3633                                                     get_session_info_system(),
3634                                                     p->msg_ctx,
3635                                                     lp_servicename(snum),
3636                                                     &pinfo2);
3637                         if (!W_ERROR_IS_OK(result)) {
3638                                 DEBUG(4, ("printserver_notify_info: "
3639                                           "Failed to get printer [%s]\n",
3640                                           lp_servicename(snum)));
3641                                 continue;
3642                         }
3643
3644
3645                         construct_notify_printer_info(p->msg_ctx,
3646                                                       Printer, info,
3647                                                       pinfo2, snum,
3648                                                       &option_type, snum,
3649                                                       mem_ctx);
3650
3651                         TALLOC_FREE(pinfo2);
3652                 }
3653         }
3654
3655 #if 0
3656         /*
3657          * Debugging information, don't delete.
3658          */
3659
3660         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3661         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3662         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3663
3664         for (i=0; i<info->count; i++) {
3665                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3666                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3667                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3668         }
3669 #endif
3670
3671         return WERR_OK;
3672 }
3673
3674 /*******************************************************************
3675  *
3676  * fill a notify_info struct with info asked
3677  *
3678  ********************************************************************/
3679
3680 static WERROR printer_notify_info(struct pipes_struct *p,
3681                                   struct policy_handle *hnd,
3682                                   struct spoolss_NotifyInfo *info,
3683                                   TALLOC_CTX *mem_ctx)
3684 {
3685         int snum;
3686         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3687         int i;
3688         uint32_t id;
3689         struct spoolss_NotifyOption *option;
3690         struct spoolss_NotifyOptionType option_type;
3691         int count,j;
3692         print_queue_struct *queue=NULL;
3693         print_status_struct status;
3694         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3695         WERROR result;
3696
3697         DEBUG(4,("printer_notify_info\n"));
3698
3699         if (!Printer)
3700                 return WERR_BADFID;
3701
3702         option = Printer->notify.option;
3703         id = 0x0;
3704
3705         info->version   = 2;
3706         info->notifies  = NULL;
3707         info->count     = 0;
3708
3709         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3710            sending a ffpcn() request first */
3711
3712         if ( !option )
3713                 return WERR_BADFID;
3714
3715         if (!get_printer_snum(p, hnd, &snum, NULL)) {
3716                 return WERR_BADFID;
3717         }
3718
3719         /* Maybe we should use the SYSTEM session_info here... */
3720         result = winreg_get_printer_internal(mem_ctx,
3721                                     get_session_info_system(),
3722                                     p->msg_ctx,
3723                                     lp_servicename(snum), &pinfo2);
3724         if (!W_ERROR_IS_OK(result)) {
3725                 return WERR_BADFID;
3726         }
3727
3728         for (i=0; i<option->count; i++) {
3729                 option_type = option->types[i];
3730
3731                 switch (option_type.type) {
3732                 case PRINTER_NOTIFY_TYPE:
3733                         if (construct_notify_printer_info(p->msg_ctx,
3734                                                           Printer, info,
3735                                                           pinfo2, snum,
3736                                                           &option_type, id,
3737                                                           mem_ctx)) {
3738                                 id--;
3739                         }
3740                         break;
3741
3742                 case JOB_NOTIFY_TYPE:
3743
3744                         count = print_queue_status(p->msg_ctx, snum, &queue,
3745                                                    &status);
3746
3747                         for (j=0; j<count; j++) {
3748                                 construct_notify_jobs_info(p->msg_ctx,
3749                                                            &queue[j], info,
3750                                                            pinfo2, snum,
3751                                                            &option_type,
3752                                                            queue[j].job,
3753                                                            mem_ctx);
3754                         }
3755
3756                         SAFE_FREE(queue);
3757                         break;
3758                 }
3759         }
3760
3761         /*
3762          * Debugging information, don't delete.
3763          */
3764         /*
3765         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3766         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3767         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3768
3769         for (i=0; i<info->count; i++) {
3770                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3771                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3772                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3773         }
3774         */
3775
3776         talloc_free(pinfo2);
3777         return WERR_OK;
3778 }
3779
3780 /****************************************************************
3781  _spoolss_RouterRefreshPrinterChangeNotify
3782 ****************************************************************/
3783
3784 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3785                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3786 {
3787         struct spoolss_NotifyInfo *info;
3788
3789         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3790         WERROR result = WERR_BADFID;
3791
3792         /* we always have a spoolss_NotifyInfo struct */
3793         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3794         if (!info) {
3795                 result = WERR_NOMEM;
3796                 goto done;
3797         }
3798
3799         *r->out.info = info;
3800
3801         if (!Printer) {
3802                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3803                         "Invalid handle (%s:%u:%u).\n",
3804                         OUR_HANDLE(r->in.handle)));
3805                 goto done;
3806         }
3807
3808         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3809
3810         /*
3811          *      We are now using the change value, and
3812          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3813          *      I don't have a global notification system, I'm sending back all the
3814          *      information even when _NOTHING_ has changed.
3815          */
3816
3817         /* We need to keep track of the change value to send back in
3818            RRPCN replies otherwise our updates are ignored. */
3819
3820         Printer->notify.fnpcn = true;
3821
3822         if (Printer->notify.cli_chan != NULL &&
3823             Printer->notify.cli_chan->active_connections > 0) {
3824                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3825                         "Saving change value in request [%x]\n",
3826                         r->in.change_low));
3827                 Printer->notify.change = r->in.change_low;
3828         }
3829
3830         /* just ignore the spoolss_NotifyOption */
3831
3832         switch (Printer->printer_type) {
3833                 case SPLHND_SERVER:
3834                         result = printserver_notify_info(p, r->in.handle,
3835                                                          info, p->mem_ctx);
3836                         break;
3837
3838                 case SPLHND_PRINTER:
3839                         result = printer_notify_info(p, r->in.handle,
3840                                                      info, p->mem_ctx);
3841                         break;
3842         }
3843
3844         Printer->notify.fnpcn = false;
3845
3846 done:
3847         return result;
3848 }
3849
3850 /********************************************************************
3851  ********************************************************************/
3852
3853 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3854                                  const char *servername,
3855                                  const char *printername,
3856                                  const char **printername_p)
3857 {
3858         /* FIXME: add lp_force_printername() */
3859
3860         if (servername == NULL) {
3861                 *printername_p = talloc_strdup(mem_ctx, printername);
3862                 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3863                 return WERR_OK;
3864         }
3865
3866         if (servername[0] == '\\' && servername[1] == '\\') {
3867                 servername += 2;
3868         }
3869
3870         *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3871         W_ERROR_HAVE_NO_MEMORY(*printername_p);
3872
3873         return WERR_OK;
3874 }
3875
3876 /********************************************************************
3877  ********************************************************************/
3878
3879 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3880                                           const char *printername)
3881 {
3882         if (dm == NULL) {
3883                 return;
3884         }
3885
3886         dm->devicename = talloc_strndup(dm, printername,
3887                                         MIN(strlen(printername), 31));
3888 }
3889
3890 /********************************************************************
3891  * construct_printer_info_0
3892  * fill a printer_info_0 struct
3893  ********************************************************************/
3894
3895 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3896                                       const struct auth_session_info *session_info,
3897                                       struct messaging_context *msg_ctx,
3898                                       struct spoolss_PrinterInfo2 *info2,
3899                                       const char *servername,
3900                                       struct spoolss_PrinterInfo0 *r,
3901                                       int snum)
3902 {
3903         int count;
3904         struct printer_session_counter *session_counter;
3905         struct timeval setuptime;
3906         print_status_struct status;
3907         WERROR result;
3908
3909         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3910         if (!W_ERROR_IS_OK(result)) {
3911                 return result;
3912         }
3913
3914         if (servername) {
3915                 r->servername = talloc_strdup(mem_ctx, servername);
3916                 W_ERROR_HAVE_NO_MEMORY(r->servername);
3917         } else {
3918                 r->servername = NULL;
3919         }
3920
3921         count = print_queue_length(msg_ctx, snum, &status);
3922
3923         /* check if we already have a counter for this printer */
3924         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3925                 if (session_counter->snum == snum)
3926                         break;
3927         }
3928
3929         /* it's the first time, add it to the list */
3930         if (session_counter == NULL) {
3931                 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3932                 W_ERROR_HAVE_NO_MEMORY(session_counter);
3933                 session_counter->snum           = snum;
3934                 session_counter->counter        = 0;
3935                 DLIST_ADD(counter_list, session_counter);
3936         }
3937
3938         /* increment it */
3939         session_counter->counter++;
3940
3941         r->cjobs                        = count;
3942         r->total_jobs                   = 0;
3943         r->total_bytes                  = 0;
3944
3945         get_startup_time(&setuptime);
3946         init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3947
3948         /* JFM:
3949          * the global_counter should be stored in a TDB as it's common to all the clients
3950          * and should be zeroed on samba startup
3951          */
3952         r->global_counter               = session_counter->counter;
3953         r->total_pages                  = 0;
3954         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3955         SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3956         SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3957         r->free_build                   = SPOOLSS_RELEASE_BUILD;
3958         r->spooling                     = 0;
3959         r->max_spooling                 = 0;
3960         r->session_counter              = session_counter->counter;
3961         r->num_error_out_of_paper       = 0x0;
3962         r->num_error_not_ready          = 0x0;          /* number of print failure */
3963         r->job_error                    = 0x0;
3964         r->number_of_processors         = 0x1;
3965         r->processor_type               = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3966         r->high_part_total_bytes        = 0x0;
3967
3968         /* ChangeID in milliseconds*/
3969         winreg_printer_get_changeid_internal(mem_ctx, session_info, msg_ctx,
3970                                     info2->sharename, &r->change_id);
3971
3972         r->last_error                   = WERR_OK;
3973         r->status                       = nt_printq_status(status.status);
3974         r->enumerate_network_printers   = 0x0;
3975         r->c_setprinter                 = 0x0;
3976         r->processor_architecture       = PROCESSOR_ARCHITECTURE_INTEL;
3977         r->processor_level              = 0x6;          /* 6  ???*/
3978         r->ref_ic                       = 0;
3979         r->reserved2                    = 0;
3980         r->reserved3                    = 0;
3981
3982         return WERR_OK;
3983 }
3984
3985
3986 /********************************************************************
3987  * construct_printer_info1
3988  * fill a spoolss_PrinterInfo1 struct
3989 ********************************************************************/
3990
3991 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3992                                       const struct spoolss_PrinterInfo2 *info2,
3993                                       uint32_t flags,
3994                                       const char *servername,
3995                                       struct spoolss_PrinterInfo1 *r,
3996                                       int snum)
3997 {
3998         WERROR result;
3999
4000         r->flags                = flags;
4001
4002         if (info2->comment == NULL || info2->comment[0] == '\0') {
4003                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
4004         } else {
4005                 r->comment      = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
4006         }
4007         W_ERROR_HAVE_NO_MEMORY(r->comment);
4008
4009         result = create_printername(mem_ctx, servername, info2->printername, &r->name);
4010         if (!W_ERROR_IS_OK(result)) {
4011                 return result;
4012         }
4013
4014         r->description          = talloc_asprintf(mem_ctx, "%s,%s,%s",
4015                                                   r->name,
4016                                                   info2->drivername,
4017                                                   r->comment);
4018         W_ERROR_HAVE_NO_MEMORY(r->description);
4019
4020         return WERR_OK;
4021 }
4022
4023 /********************************************************************
4024  * construct_printer_info2
4025  * fill a spoolss_PrinterInfo2 struct
4026 ********************************************************************/
4027
4028 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
4029                                       struct messaging_context *msg_ctx,
4030                                       const struct spoolss_PrinterInfo2 *info2,
4031                                       const char *servername,
4032                                       struct spoolss_PrinterInfo2 *r,
4033                                       int snum)
4034 {
4035         int count;
4036         print_status_struct status;
4037         WERROR result;
4038
4039         count = print_queue_length(msg_ctx, snum, &status);
4040
4041         if (servername) {
4042                 r->servername           = talloc_strdup(mem_ctx, servername);
4043                 W_ERROR_HAVE_NO_MEMORY(r->servername);
4044         } else {
4045                 r->servername           = NULL;
4046         }
4047
4048         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4049         if (!W_ERROR_IS_OK(result)) {
4050                 return result;
4051         }
4052
4053         r->sharename            = talloc_strdup(mem_ctx, lp_servicename(snum));
4054         W_ERROR_HAVE_NO_MEMORY(r->sharename);
4055         r->portname             = talloc_strdup(mem_ctx, info2->portname);
4056         W_ERROR_HAVE_NO_MEMORY(r->portname);
4057         r->drivername           = talloc_strdup(mem_ctx, info2->drivername);
4058         W_ERROR_HAVE_NO_MEMORY(r->drivername);
4059
4060         if (info2->comment[0] == '\0') {
4061                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
4062         } else {
4063                 r->comment      = talloc_strdup(mem_ctx, info2->comment);
4064         }
4065         W_ERROR_HAVE_NO_MEMORY(r->comment);
4066
4067         r->location     = talloc_strdup(mem_ctx, info2->location);
4068         if (info2->location[0] == '\0') {
4069                 const char *loc = NULL;
4070                 NTSTATUS nt_status;
4071
4072                 nt_status = printer_list_get_printer(mem_ctx,
4073                                                      info2->sharename,
4074                                                      NULL,
4075                                                      &loc,
4076                                                      NULL);
4077                 if (NT_STATUS_IS_OK(nt_status)) {
4078                         if (loc != NULL) {
4079                                 r->location = talloc_strdup(mem_ctx, loc);
4080                         }
4081                 }
4082         }
4083         W_ERROR_HAVE_NO_MEMORY(r->location);
4084
4085         r->sepfile              = talloc_strdup(mem_ctx, info2->sepfile);
4086         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4087         r->printprocessor       = talloc_strdup(mem_ctx, info2->printprocessor);
4088         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4089         r->datatype             = talloc_strdup(mem_ctx, info2->datatype);
4090         W_ERROR_HAVE_NO_MEMORY(r->datatype);
4091         r->parameters           = talloc_strdup(mem_ctx, info2->parameters);
4092         W_ERROR_HAVE_NO_MEMORY(r->parameters);
4093
4094         r->attributes           = info2->attributes;
4095
4096         r->priority             = info2->priority;
4097         r->defaultpriority      = info2->defaultpriority;
4098         r->starttime            = info2->starttime;
4099         r->untiltime            = info2->untiltime;
4100         r->status               = nt_printq_status(status.status);
4101         r->cjobs                = count;
4102         r->averageppm           = info2->averageppm;
4103
4104         copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4105         if (!r->devmode) {
4106                 DEBUG(8,("Returning NULL Devicemode!\n"));
4107         }
4108
4109         compose_devicemode_devicename(r->devmode, r->printername);
4110
4111         r->secdesc = NULL;
4112
4113         if (info2->secdesc != NULL) {
4114                 /* don't use talloc_steal() here unless you do a deep steal of all
4115                    the SEC_DESC members */
4116
4117                 r->secdesc      = dup_sec_desc(mem_ctx, info2->secdesc);
4118         }
4119
4120         return WERR_OK;
4121 }
4122
4123 /********************************************************************
4124  * construct_printer_info3
4125  * fill a spoolss_PrinterInfo3 struct
4126  ********************************************************************/
4127
4128 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4129                                       const struct spoolss_PrinterInfo2 *info2,
4130                                       const char *servername,
4131                                       struct spoolss_PrinterInfo3 *r,
4132                                       int snum)
4133 {
4134         /* These are the components of the SD we are returning. */
4135
4136         if (info2->secdesc != NULL) {
4137                 /* don't use talloc_steal() here unless you do a deep steal of all
4138                    the SEC_DESC members */
4139
4140                 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4141                 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
4142         }
4143
4144         return WERR_OK;
4145 }
4146
4147 /********************************************************************
4148  * construct_printer_info4
4149  * fill a spoolss_PrinterInfo4 struct
4150  ********************************************************************/
4151
4152 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4153                                       const struct spoolss_PrinterInfo2 *info2,
4154                                       const char *servername,
4155                                       struct spoolss_PrinterInfo4 *r,
4156                                       int snum)
4157 {
4158         WERROR result;
4159
4160         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4161         if (!W_ERROR_IS_OK(result)) {
4162                 return result;
4163         }
4164
4165         if (servername) {
4166                 r->servername   = talloc_strdup(mem_ctx, servername);
4167                 W_ERROR_HAVE_NO_MEMORY(r->servername);
4168         } else {
4169                 r->servername = NULL;
4170         }
4171
4172         r->attributes   = info2->attributes;
4173
4174         return WERR_OK;
4175 }
4176
4177 /********************************************************************
4178  * construct_printer_info5
4179  * fill a spoolss_PrinterInfo5 struct
4180  ********************************************************************/
4181
4182 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4183                                       const struct spoolss_PrinterInfo2 *info2,
4184                                       const char *servername,
4185                                       struct spoolss_PrinterInfo5 *r,
4186                                       int snum)
4187 {
4188         WERROR result;
4189
4190         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4191         if (!W_ERROR_IS_OK(result)) {
4192                 return result;
4193         }
4194
4195         r->portname     = talloc_strdup(mem_ctx, info2->portname);
4196         W_ERROR_HAVE_NO_MEMORY(r->portname);
4197
4198         r->attributes   = info2->attributes;
4199
4200         /* these two are not used by NT+ according to MSDN */
4201         r->device_not_selected_timeout          = 0x0;  /* have seen 0x3a98 */
4202         r->transmission_retry_timeout           = 0x0;  /* have seen 0xafc8 */
4203
4204         return WERR_OK;
4205 }
4206
4207 /********************************************************************
4208  * construct_printer_info_6
4209  * fill a spoolss_PrinterInfo6 struct
4210  ********************************************************************/
4211
4212 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4213                                       struct messaging_context *msg_ctx,
4214                                       const struct spoolss_PrinterInfo2 *info2,
4215                                       const char *servername,
4216                                       struct spoolss_PrinterInfo6 *r,
4217                                       int snum)
4218 {
4219         print_status_struct status;
4220
4221         print_queue_length(msg_ctx, snum, &status);
4222
4223         r->status = nt_printq_status(status.status);
4224
4225         return WERR_OK;
4226 }
4227
4228 /********************************************************************
4229  * construct_printer_info7
4230  * fill a spoolss_PrinterInfo7 struct
4231  ********************************************************************/
4232
4233 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4234                                       struct messaging_context *msg_ctx,
4235                                       const char *servername,
4236                                       struct spoolss_PrinterInfo7 *r,
4237                                       int snum)
4238 {
4239         const struct auth_session_info *session_info = get_session_info_system();
4240         struct GUID guid;
4241
4242         if (is_printer_published(mem_ctx, session_info, msg_ctx,
4243                                  servername,
4244                                  lp_servicename(snum), &guid, NULL)) {
4245                 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4246                 r->action = DSPRINT_PUBLISH;
4247         } else {
4248                 r->guid = talloc_strdup(mem_ctx, "");
4249                 r->action = DSPRINT_UNPUBLISH;
4250         }
4251         W_ERROR_HAVE_NO_MEMORY(r->guid);
4252
4253         return WERR_OK;
4254 }
4255
4256 /********************************************************************
4257  * construct_printer_info8
4258  * fill a spoolss_PrinterInfo8 struct
4259  ********************************************************************/
4260
4261 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4262                                       const struct spoolss_PrinterInfo2 *info2,
4263                                       const char *servername,
4264                                       struct spoolss_DeviceModeInfo *r,
4265                                       int snum)
4266 {
4267         WERROR result;
4268         const char *printername;
4269
4270         result = create_printername(mem_ctx, servername, info2->printername, &printername);
4271         if (!W_ERROR_IS_OK(result)) {
4272                 return result;
4273         }
4274
4275         copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4276         if (!r->devmode) {
4277                 DEBUG(8,("Returning NULL Devicemode!\n"));
4278         }
4279
4280         compose_devicemode_devicename(r->devmode, printername);
4281
4282         return WERR_OK;
4283 }
4284
4285
4286 /********************************************************************
4287 ********************************************************************/
4288
4289 static bool snum_is_shared_printer(int snum)
4290 {
4291         return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4292 }
4293
4294 /********************************************************************
4295  Spoolss_enumprinters.
4296 ********************************************************************/
4297
4298 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4299                                            const struct auth_session_info *session_info,
4300                                            struct messaging_context *msg_ctx,
4301                                            const char *servername,
4302                                            uint32_t level,
4303                                            uint32_t flags,
4304                                            union spoolss_PrinterInfo **info_p,
4305                                            uint32_t *count_p)
4306 {
4307         int snum;
4308         int n_services = lp_numservices();
4309         union spoolss_PrinterInfo *info = NULL;
4310         uint32_t count = 0;
4311         WERROR result = WERR_OK;
4312         struct dcerpc_binding_handle *b = NULL;
4313         TALLOC_CTX *tmp_ctx = NULL;
4314
4315         tmp_ctx = talloc_new(mem_ctx);
4316         if (!tmp_ctx) {
4317                 return WERR_NOMEM;
4318         }
4319
4320         *count_p = 0;
4321         *info_p = NULL;
4322
4323         for (snum = 0; snum < n_services; snum++) {
4324
4325                 const char *printer;
4326                 struct spoolss_PrinterInfo2 *info2;
4327
4328                 if (!snum_is_shared_printer(snum)) {
4329                         continue;
4330                 }
4331
4332                 printer = lp_const_servicename(snum);
4333
4334                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4335                         printer, snum));
4336
4337                 if (b == NULL) {
4338                         result = winreg_printer_binding_handle(tmp_ctx,
4339                                                                session_info,
4340                                                                msg_ctx,
4341                                                                &b);
4342                         if (!W_ERROR_IS_OK(result)) {
4343                                 goto out;
4344                         }
4345                 }
4346
4347                 result = winreg_create_printer(tmp_ctx, b,
4348                                                printer);
4349                 if (!W_ERROR_IS_OK(result)) {
4350                         goto out;
4351                 }
4352
4353                 info = talloc_realloc(tmp_ctx, info,
4354                                             union spoolss_PrinterInfo,
4355                                             count + 1);
4356                 if (!info) {
4357                         result = WERR_NOMEM;
4358                         goto out;
4359                 }
4360
4361                 result = winreg_get_printer(tmp_ctx, b,
4362                                             printer, &info2);
4363                 if (!W_ERROR_IS_OK(result)) {
4364                         goto out;
4365                 }
4366
4367                 switch (level) {
4368                 case 0:
4369                         result = construct_printer_info0(info, session_info,
4370                                                          msg_ctx, info2,
4371                                                          servername,
4372                                                          &info[count].info0, snum);
4373                         break;
4374                 case 1:
4375                         result = construct_printer_info1(info, info2, flags,
4376                                                          servername,
4377                                                          &info[count].info1, snum);
4378                         break;
4379                 case 2:
4380                         result = construct_printer_info2(info, msg_ctx, info2,
4381                                                          servername,
4382                                                          &info[count].info2, snum);
4383                         break;
4384                 case 4:
4385                         result = construct_printer_info4(info, info2,
4386                                                          servername,
4387                                                          &info[count].info4, snum);
4388                         break;
4389                 case 5:
4390                         result = construct_printer_info5(info, info2,
4391                                                          servername,
4392                                                          &info[count].info5, snum);
4393                         break;
4394
4395                 default:
4396                         result = WERR_UNKNOWN_LEVEL;
4397                         goto out;
4398                 }
4399
4400                 if (!W_ERROR_IS_OK(result)) {
4401                         goto out;
4402                 }
4403
4404                 count++;
4405         }
4406
4407 out:
4408         if (W_ERROR_IS_OK(result)) {
4409                 *info_p = talloc_move(mem_ctx, &info);
4410                 *count_p = count;
4411         }
4412
4413         talloc_free(tmp_ctx);
4414
4415         return result;
4416 }
4417
4418 /********************************************************************
4419  * handle enumeration of printers at level 0
4420  ********************************************************************/
4421
4422 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4423                                   const struct auth_session_info *session_info,
4424                                   struct messaging_context *msg_ctx,
4425                                   uint32_t flags,
4426                                   const char *servername,
4427                                   union spoolss_PrinterInfo **info,
4428                                   uint32_t *count)
4429 {
4430         DEBUG(4,("enum_all_printers_info_0\n"));
4431
4432         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4433                                             servername, 0, flags, info, count);
4434 }
4435
4436
4437 /********************************************************************
4438 ********************************************************************/
4439
4440 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4441                                        const struct auth_session_info *session_info,
4442                                        struct messaging_context *msg_ctx,
4443                                        const char *servername,
4444                                        uint32_t flags,
4445                                        union spoolss_PrinterInfo **info,
4446                                        uint32_t *count)
4447 {
4448         DEBUG(4,("enum_all_printers_info_1\n"));
4449
4450         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4451                                             servername, 1, flags, info, count);
4452 }
4453
4454 /********************************************************************
4455  enum_all_printers_info_1_local.
4456 *********************************************************************/
4457
4458 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4459                                              const struct auth_session_info *session_info,
4460                                              struct messaging_context *msg_ctx,
4461                                              const char *servername,
4462                                              union spoolss_PrinterInfo **info,
4463                                              uint32_t *count)
4464 {
4465         DEBUG(4,("enum_all_printers_info_1_local\n"));
4466
4467         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4468                                         servername, PRINTER_ENUM_ICON8, info, count);
4469 }
4470
4471 /********************************************************************
4472  enum_all_printers_info_1_name.
4473 *********************************************************************/
4474
4475 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4476                                             const struct auth_session_info *session_info,
4477                                             struct messaging_context *msg_ctx,
4478                                             const char *servername,
4479                                             union spoolss_PrinterInfo **info,
4480                                             uint32_t *count)
4481 {
4482         const char *s = servername;
4483
4484         DEBUG(4,("enum_all_printers_info_1_name\n"));
4485
4486         if ((servername[0] == '\\') && (servername[1] == '\\')) {
4487                 s = servername + 2;
4488         }
4489
4490         if (!is_myname_or_ipaddr(s)) {
4491                 return WERR_INVALID_NAME;
4492         }
4493
4494         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4495                                         servername, PRINTER_ENUM_ICON8, info, count);
4496 }
4497
4498 /********************************************************************
4499  enum_all_printers_info_1_network.
4500 *********************************************************************/
4501
4502 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4503                                                const struct auth_session_info *session_info,
4504                                                struct messaging_context *msg_ctx,
4505                                                const char *servername,
4506                                                union spoolss_PrinterInfo **info,
4507                                                uint32_t *count)
4508 {
4509         const char *s = servername;
4510
4511         DEBUG(4,("enum_all_printers_info_1_network\n"));
4512
4513         /* If we respond to a enum_printers level 1 on our name with flags
4514            set to PRINTER_ENUM_REMOTE with a list of printers then these
4515            printers incorrectly appear in the APW browse list.
4516            Specifically the printers for the server appear at the workgroup
4517            level where all the other servers in the domain are
4518            listed. Windows responds to this call with a
4519            WERR_CAN_NOT_COMPLETE so we should do the same. */
4520
4521         if (servername[0] == '\\' && servername[1] == '\\') {
4522                  s = servername + 2;
4523         }
4524
4525         if (is_myname_or_ipaddr(s)) {
4526                  return WERR_CAN_NOT_COMPLETE;
4527         }
4528
4529         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4530                                         servername, PRINTER_ENUM_NAME, info, count);
4531 }
4532
4533 /********************************************************************
4534  * api_spoolss_enumprinters
4535  *
4536  * called from api_spoolss_enumprinters (see this to understand)
4537  ********************************************************************/
4538
4539 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4540                                        const struct auth_session_info *session_info,
4541                                        struct messaging_context *msg_ctx,
4542                                        const char *servername,
4543                                        union spoolss_PrinterInfo **info,
4544                                        uint32_t *count)
4545 {
4546         DEBUG(4,("enum_all_printers_info_2\n"));
4547
4548         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4549                                             servername, 2, 0, info, count);
4550 }
4551
4552 /********************************************************************
4553  * handle enumeration of printers at level 1
4554  ********************************************************************/
4555
4556 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4557                                   const struct auth_session_info *session_info,
4558                                   struct messaging_context *msg_ctx,
4559                                   uint32_t flags,
4560                                   const char *servername,
4561                                   union spoolss_PrinterInfo **info,
4562                                   uint32_t *count)
4563 {
4564         /* Not all the flags are equals */
4565
4566         if (flags & PRINTER_ENUM_LOCAL) {
4567                 return enum_all_printers_info_1_local(mem_ctx, session_info,
4568                                                       msg_ctx, servername, info, count);
4569         }
4570
4571         if (flags & PRINTER_ENUM_NAME) {
4572                 return enum_all_printers_info_1_name(mem_ctx, session_info,
4573                                                      msg_ctx, servername, info,
4574                                                      count);
4575         }
4576
4577         if (flags & PRINTER_ENUM_NETWORK) {
4578                 return enum_all_printers_info_1_network(mem_ctx, session_info,
4579                                                         msg_ctx, servername, info,
4580                                                         count);
4581         }
4582
4583         return WERR_OK; /* NT4sp5 does that */
4584 }
4585
4586 /********************************************************************
4587  * handle enumeration of printers at level 2
4588  ********************************************************************/
4589
4590 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4591                                   const struct auth_session_info *session_info,
4592                                   struct messaging_context *msg_ctx,
4593                                   uint32_t flags,
4594                                   const char *servername,
4595                                   union spoolss_PrinterInfo **info,
4596                                   uint32_t *count)
4597 {
4598         if (flags & PRINTER_ENUM_LOCAL) {
4599
4600                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4601                                                 servername,
4602                                                 info, count);
4603         }
4604
4605         if (flags & PRINTER_ENUM_NAME) {
4606                 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4607                         return WERR_INVALID_NAME;
4608                 }
4609
4610                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4611                                                 servername,
4612                                                 info, count);
4613         }
4614
4615         if (flags & PRINTER_ENUM_REMOTE) {
4616                 return WERR_UNKNOWN_LEVEL;
4617         }
4618
4619         return WERR_OK;
4620 }
4621
4622 /********************************************************************
4623  * handle enumeration of printers at level 4
4624  ********************************************************************/
4625
4626 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4627                                   const struct auth_session_info *session_info,
4628                                   struct messaging_context *msg_ctx,
4629                                   uint32_t flags,
4630                                   const char *servername,
4631                                   union spoolss_PrinterInfo **info,
4632                                   uint32_t *count)
4633 {
4634         DEBUG(4,("enum_all_printers_info_4\n"));
4635
4636         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4637                                             servername, 4, flags, info, count);
4638 }
4639
4640
4641 /********************************************************************
4642  * handle enumeration of printers at level 5
4643  ********************************************************************/
4644
4645 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4646                                   const struct auth_session_info *session_info,
4647                                   struct messaging_context *msg_ctx,
4648                                   uint32_t flags,
4649                                   const char *servername,
4650                                   union spoolss_PrinterInfo **info,
4651                                   uint32_t *count)
4652 {
4653         DEBUG(4,("enum_all_printers_info_5\n"));
4654
4655         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4656                                             servername, 5, flags, info, count);
4657 }
4658
4659 /****************************************************************
4660  _spoolss_EnumPrinters
4661 ****************************************************************/
4662
4663 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4664                              struct spoolss_EnumPrinters *r)
4665 {
4666         const struct auth_session_info *session_info = get_session_info_system();
4667         WERROR result;
4668
4669         /* that's an [in out] buffer */
4670
4671         if (!r->in.buffer && (r->in.offered != 0)) {
4672                 return WERR_INVALID_PARAM;
4673         }
4674
4675         DEBUG(4,("_spoolss_EnumPrinters\n"));
4676
4677         *r->out.needed = 0;
4678         *r->out.count = 0;
4679         *r->out.info = NULL;
4680
4681         /*
4682          * Level 1:
4683          *          flags==PRINTER_ENUM_NAME
4684          *           if name=="" then enumerates all printers
4685          *           if name!="" then enumerate the printer
4686          *          flags==PRINTER_ENUM_REMOTE
4687          *          name is NULL, enumerate printers
4688          * Level 2: name!="" enumerates printers, name can't be NULL
4689          * Level 3: doesn't exist
4690          * Level 4: does a local registry lookup
4691          * Level 5: same as Level 2
4692          */
4693
4694         if (r->in.server && r->in.server[0] == '\0') {
4695                 r->in.server = NULL;
4696         }
4697
4698         switch (r->in.level) {
4699         case 0:
4700                 result = enumprinters_level0(p->mem_ctx, session_info,
4701                                              p->msg_ctx, r->in.flags,
4702                                              r->in.server,
4703                                              r->out.info, r->out.count);
4704                 break;
4705         case 1:
4706                 result = enumprinters_level1(p->mem_ctx, session_info,
4707                                              p->msg_ctx, r->in.flags,
4708                                              r->in.server,
4709                                              r->out.info, r->out.count);
4710                 break;
4711         case 2:
4712                 result = enumprinters_level2(p->mem_ctx, session_info,
4713                                              p->msg_ctx, r->in.flags,
4714                                              r->in.server,
4715                                              r->out.info, r->out.count);
4716                 break;
4717         case 4:
4718                 result = enumprinters_level4(p->mem_ctx, session_info,
4719                                              p->msg_ctx, r->in.flags,
4720                                              r->in.server,
4721                                              r->out.info, r->out.count);
4722                 break;
4723         case 5:
4724                 result = enumprinters_level5(p->mem_ctx, session_info,
4725                                              p->msg_ctx, r->in.flags,
4726                                              r->in.server,
4727                                              r->out.info, r->out.count);
4728                 break;
4729         default:
4730                 return WERR_UNKNOWN_LEVEL;
4731         }
4732
4733         if (!W_ERROR_IS_OK(result)) {
4734                 return result;
4735         }
4736
4737         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4738                                                      spoolss_EnumPrinters,
4739                                                      *r->out.info, r->in.level,
4740                                                      *r->out.count);
4741         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4742         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4743
4744         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4745 }
4746
4747 /****************************************************************
4748  _spoolss_GetPrinter
4749 ****************************************************************/
4750
4751 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4752                            struct spoolss_GetPrinter *r)
4753 {
4754         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4755         struct spoolss_PrinterInfo2 *info2 = NULL;
4756         WERROR result = WERR_OK;
4757         int snum;
4758
4759         /* that's an [in out] buffer */
4760
4761         if (!r->in.buffer && (r->in.offered != 0)) {
4762                 return WERR_INVALID_PARAM;
4763         }
4764
4765         *r->out.needed = 0;
4766
4767         if (Printer == NULL) {
4768                 return WERR_BADFID;
4769         }
4770
4771         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4772                 return WERR_BADFID;
4773         }
4774
4775         result = winreg_get_printer_internal(p->mem_ctx,
4776                                     get_session_info_system(),
4777                                     p->msg_ctx,
4778                                     lp_const_servicename(snum),
4779                                     &info2);
4780         if (!W_ERROR_IS_OK(result)) {
4781                 goto out;
4782         }
4783
4784         switch (r->in.level) {
4785         case 0:
4786                 result = construct_printer_info0(p->mem_ctx,
4787                                                  get_session_info_system(),
4788                                                  p->msg_ctx,
4789                                                  info2,
4790                                                  Printer->servername,
4791                                                  &r->out.info->info0,
4792                                                  snum);
4793                 break;
4794         case 1:
4795                 result = construct_printer_info1(p->mem_ctx, info2,
4796                                                  PRINTER_ENUM_ICON8,
4797                                                  Printer->servername,
4798                                                  &r->out.info->info1, snum);
4799                 break;
4800         case 2:
4801                 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4802                                                  Printer->servername,
4803                                                  &r->out.info->info2, snum);
4804                 break;
4805         case 3:
4806                 result = construct_printer_info3(p->mem_ctx, info2,
4807                                                  Printer->servername,
4808                                                  &r->out.info->info3, snum);
4809                 break;
4810         case 4:
4811                 result = construct_printer_info4(p->mem_ctx, info2,
4812                                                  Printer->servername,
4813                                                  &r->out.info->info4, snum);
4814                 break;
4815         case 5:
4816                 result = construct_printer_info5(p->mem_ctx, info2,
4817                                                  Printer->servername,
4818                                                  &r->out.info->info5, snum);
4819                 break;
4820         case 6:
4821                 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4822                                                  Printer->servername,
4823                                                  &r->out.info->info6, snum);
4824                 break;
4825         case 7:
4826                 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4827                                                  Printer->servername,
4828                                                  &r->out.info->info7, snum);
4829                 break;
4830         case 8:
4831                 result = construct_printer_info8(p->mem_ctx, info2,
4832                                                  Printer->servername,
4833                                                  &r->out.info->info8, snum);
4834                 break;
4835         default:
4836                 result = WERR_UNKNOWN_LEVEL;
4837                 break;
4838         }
4839         TALLOC_FREE(info2);
4840
4841  out:
4842         if (!W_ERROR_IS_OK(result)) {
4843                 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4844                           r->in.level, win_errstr(result)));
4845                 TALLOC_FREE(r->out.info);
4846                 return result;
4847         }
4848
4849         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4850                                                r->out.info, r->in.level);
4851         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4852
4853         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4854 }
4855
4856 /********************************************************************
4857  ********************************************************************/
4858
4859 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4860         do { \
4861                 if (in && strlen(in)) { \
4862                         out = talloc_strdup(mem_ctx, in); \
4863                 } else { \
4864                         out = talloc_strdup(mem_ctx, ""); \
4865                 } \
4866                 W_ERROR_HAVE_NO_MEMORY(out); \
4867         } while (0);
4868
4869 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4870         do { \
4871                 if (in && strlen(in)) { \
4872                         out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4873                 } else { \
4874                         out = talloc_strdup(mem_ctx, ""); \
4875                 } \
4876                 W_ERROR_HAVE_NO_MEMORY(out); \
4877         } while (0);
4878
4879 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4880                                                   const char **string_array,
4881                                                   const char ***presult,
4882                                                   const char *cservername,
4883                                                   const char *arch,
4884                                                   int version)
4885 {
4886         int i, num_strings = 0;
4887         const char **array = NULL;
4888
4889         if (string_array == NULL) {
4890                 return WERR_INVALID_PARAMETER;
4891         }
4892
4893         for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4894                 const char *str = NULL;
4895
4896                 if (cservername == NULL || arch == NULL) {
4897                         FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4898                 } else {
4899                         FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4900                 }
4901
4902                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4903                         TALLOC_FREE(array);
4904                         return WERR_NOMEM;
4905                 }
4906         }
4907
4908         if (i > 0) {
4909                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4910                              &array, &num_strings);
4911         }
4912
4913         if (presult) {
4914                 *presult = array;
4915         }
4916
4917         return WERR_OK;
4918 }
4919
4920 /********************************************************************
4921  * fill a spoolss_DriverInfo1 struct
4922  ********************************************************************/
4923
4924 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4925                                         struct spoolss_DriverInfo1 *r,
4926                                         const struct spoolss_DriverInfo8 *driver,
4927                                         const char *servername)
4928 {
4929         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4930         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4931
4932         return WERR_OK;
4933 }
4934
4935 /********************************************************************
4936  * fill a spoolss_DriverInfo2 struct
4937  ********************************************************************/
4938
4939 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4940                                         struct spoolss_DriverInfo2 *r,
4941                                         const struct spoolss_DriverInfo8 *driver,
4942                                         const char *servername)
4943
4944 {
4945         const char *cservername = canon_servername(servername);
4946
4947         r->version              = driver->version;
4948
4949         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4950         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4951         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4952         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4953
4954         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4955                                driver->architecture,
4956                                driver->version,
4957                                driver->driver_path,
4958                                r->driver_path);
4959
4960         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4961                                driver->architecture,
4962                                driver->version,
4963                                driver->data_file,
4964                                r->data_file);
4965
4966         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4967                                driver->architecture,
4968                                driver->version,
4969                                driver->config_file,
4970                                r->config_file);
4971
4972         return WERR_OK;
4973 }
4974
4975 /********************************************************************
4976  * fill a spoolss_DriverInfo3 struct
4977  ********************************************************************/
4978
4979 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4980                                         struct spoolss_DriverInfo3 *r,
4981                                         const struct spoolss_DriverInfo8 *driver,
4982                                         const char *servername)
4983 {
4984         const char *cservername = canon_servername(servername);
4985
4986         r->version              = driver->version;
4987
4988         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4989         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4990         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4991         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4992
4993         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4994                                driver->architecture,
4995                                driver->version,
4996                                driver->driver_path,
4997                                r->driver_path);
4998
4999         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5000                                driver->architecture,
5001                                driver->version,
5002                                driver->data_file,
5003                                r->data_file);
5004
5005         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5006                                driver->architecture,
5007                                driver->version,
5008                                driver->config_file,
5009                                r->config_file);
5010
5011         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5012                                driver->architecture,
5013                                driver->version,
5014                                driver->help_file,
5015                                r->help_file);
5016
5017         FILL_DRIVER_STRING(mem_ctx,
5018                            driver->monitor_name,
5019                            r->monitor_name);
5020
5021         FILL_DRIVER_STRING(mem_ctx,
5022                            driver->default_datatype,
5023                            r->default_datatype);
5024
5025         return string_array_from_driver_info(mem_ctx,
5026                                              driver->dependent_files,
5027                                              &r->dependent_files,
5028                                              cservername,
5029                                              driver->architecture,
5030                                              driver->version);
5031 }
5032
5033 /********************************************************************
5034  * fill a spoolss_DriverInfo4 struct
5035  ********************************************************************/
5036
5037 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
5038                                         struct spoolss_DriverInfo4 *r,
5039                                         const struct spoolss_DriverInfo8 *driver,
5040                                         const char *servername)
5041 {
5042         const char *cservername = canon_servername(servername);
5043         WERROR result;
5044
5045         r->version              = driver->version;
5046
5047         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5048         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5049         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5050         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5051
5052         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5053                                driver->architecture,
5054                                driver->version,
5055                                driver->driver_path,
5056                                r->driver_path);
5057
5058         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5059                                driver->architecture,
5060                                driver->version,
5061                                driver->data_file,
5062                                r->data_file);
5063
5064         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5065                                driver->architecture,
5066                                driver->version,
5067                                driver->config_file,
5068                                r->config_file);
5069
5070         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5071                                driver->architecture,
5072                                driver->version,
5073                                driver->help_file,
5074                                r->help_file);
5075
5076         result = string_array_from_driver_info(mem_ctx,
5077                                                driver->dependent_files,
5078                                                &r->dependent_files,
5079                                                cservername,
5080                                                driver->architecture,
5081                                                driver->version);
5082         if (!W_ERROR_IS_OK(result)) {
5083                 return result;
5084         }
5085
5086         FILL_DRIVER_STRING(mem_ctx,
5087                            driver->monitor_name,
5088                            r->monitor_name);
5089
5090         FILL_DRIVER_STRING(mem_ctx,
5091                            driver->default_datatype,
5092                            r->default_datatype);
5093
5094
5095         result = string_array_from_driver_info(mem_ctx,
5096                                                driver->previous_names,
5097                                                &r->previous_names,
5098                                                NULL, NULL, 0);
5099
5100         return result;
5101 }
5102
5103 /********************************************************************
5104  * fill a spoolss_DriverInfo5 struct
5105  ********************************************************************/
5106
5107 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5108                                         struct spoolss_DriverInfo5 *r,
5109                                         const struct spoolss_DriverInfo8 *driver,
5110                                         const char *servername)
5111 {
5112         const char *cservername = canon_servername(servername);
5113
5114         r->version              = driver->version;
5115
5116         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5117         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5118         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5119         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5120
5121         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5122                                driver->architecture,
5123                                driver->version,
5124                                driver->driver_path,
5125                                r->driver_path);
5126
5127         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5128                                driver->architecture,
5129                                driver->version,
5130                                driver->data_file,
5131                                r->data_file);
5132
5133         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5134                                driver->architecture,
5135                                driver->version,
5136                                driver->config_file,
5137                                r->config_file);
5138
5139         r->driver_attributes    = 0;
5140         r->config_version       = 0;
5141         r->driver_version       = 0;
5142
5143         return WERR_OK;
5144 }
5145 /********************************************************************
5146  * fill a spoolss_DriverInfo6 struct
5147  ********************************************************************/
5148
5149 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5150                                         struct spoolss_DriverInfo6 *r,
5151                                         const struct spoolss_DriverInfo8 *driver,
5152                                         const char *servername)
5153 {
5154         const char *cservername = canon_servername(servername);
5155         WERROR result;
5156
5157         r->version              = driver->version;
5158
5159         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5160         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5161         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5162         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5163
5164         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5165                                driver->architecture,
5166                                driver->version,
5167                                driver->driver_path,
5168                                r->driver_path);
5169
5170         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5171                                driver->architecture,
5172                                driver->version,
5173                                driver->data_file,
5174                                r->data_file);
5175
5176         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5177                                driver->architecture,
5178                                driver->version,
5179                                driver->config_file,
5180                                r->config_file);
5181
5182         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5183                                driver->architecture,
5184                                driver->version,
5185                                driver->help_file,
5186                                r->help_file);
5187
5188         FILL_DRIVER_STRING(mem_ctx,
5189                            driver->monitor_name,
5190                            r->monitor_name);
5191
5192         FILL_DRIVER_STRING(mem_ctx,
5193                            driver->default_datatype,
5194                            r->default_datatype);
5195
5196         result = string_array_from_driver_info(mem_ctx,
5197                                                driver->dependent_files,
5198                                                &r->dependent_files,
5199                                                cservername,
5200                                                driver->architecture,
5201                                                driver->version);
5202         if (!W_ERROR_IS_OK(result)) {
5203                 return result;
5204         }
5205
5206         result = string_array_from_driver_info(mem_ctx,
5207                                                driver->previous_names,
5208                                                &r->previous_names,
5209                                                NULL, NULL, 0);
5210         if (!W_ERROR_IS_OK(result)) {
5211                 return result;
5212         }
5213
5214         r->driver_date          = driver->driver_date;
5215         r->driver_version       = driver->driver_version;
5216
5217         FILL_DRIVER_STRING(mem_ctx,
5218                            driver->manufacturer_name,
5219                            r->manufacturer_name);
5220         FILL_DRIVER_STRING(mem_ctx,
5221                            driver->manufacturer_url,
5222                            r->manufacturer_url);
5223         FILL_DRIVER_STRING(mem_ctx,
5224                            driver->hardware_id,
5225                            r->hardware_id);
5226         FILL_DRIVER_STRING(mem_ctx,
5227                            driver->provider,
5228                            r->provider);
5229
5230         return WERR_OK;
5231 }
5232
5233 /********************************************************************
5234  * fill a spoolss_DriverInfo8 struct
5235  ********************************************************************/
5236
5237 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5238                                         struct spoolss_DriverInfo8 *r,
5239                                         const struct spoolss_DriverInfo8 *driver,
5240                                         const char *servername)
5241 {
5242         const char *cservername = canon_servername(servername);
5243         WERROR result;
5244
5245         r->version              = driver->version;
5246
5247         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5248         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5249         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5250         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5251
5252         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5253                                driver->architecture,
5254                                driver->version,
5255                                driver->driver_path,
5256                                r->driver_path);
5257
5258         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5259                                driver->architecture,
5260                                driver->version,
5261                                driver->data_file,
5262                                r->data_file);
5263
5264         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5265                                driver->architecture,
5266                                driver->version,
5267                                driver->config_file,
5268                                r->config_file);
5269
5270         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5271                                driver->architecture,
5272                                driver->version,
5273                                driver->help_file,
5274                                r->help_file);
5275
5276         FILL_DRIVER_STRING(mem_ctx,
5277                            driver->monitor_name,
5278                            r->monitor_name);
5279
5280         FILL_DRIVER_STRING(mem_ctx,
5281                            driver->default_datatype,
5282                            r->default_datatype);
5283
5284         result = string_array_from_driver_info(mem_ctx,
5285                                                driver->dependent_files,
5286                                                &r->dependent_files,
5287                                                cservername,
5288                                                driver->architecture,
5289                                                driver->version);
5290         if (!W_ERROR_IS_OK(result)) {
5291                 return result;
5292         }
5293
5294         result = string_array_from_driver_info(mem_ctx,
5295                                                driver->previous_names,
5296                                                &r->previous_names,
5297                                                NULL, NULL, 0);
5298         if (!W_ERROR_IS_OK(result)) {
5299                 return result;
5300         }
5301
5302         r->driver_date          = driver->driver_date;
5303         r->driver_version       = driver->driver_version;
5304
5305         FILL_DRIVER_STRING(mem_ctx,
5306                            driver->manufacturer_name,
5307                            r->manufacturer_name);
5308         FILL_DRIVER_STRING(mem_ctx,
5309                            driver->manufacturer_url,
5310                            r->manufacturer_url);
5311         FILL_DRIVER_STRING(mem_ctx,
5312                            driver->hardware_id,
5313                            r->hardware_id);
5314         FILL_DRIVER_STRING(mem_ctx,
5315                            driver->provider,
5316                            r->provider);
5317
5318         FILL_DRIVER_STRING(mem_ctx,
5319                            driver->print_processor,
5320                            r->print_processor);
5321         FILL_DRIVER_STRING(mem_ctx,
5322                            driver->vendor_setup,
5323                            r->vendor_setup);
5324
5325         result = string_array_from_driver_info(mem_ctx,
5326                                                driver->color_profiles,
5327                                                &r->color_profiles,
5328                                                NULL, NULL, 0);
5329         if (!W_ERROR_IS_OK(result)) {
5330                 return result;
5331         }
5332
5333         FILL_DRIVER_STRING(mem_ctx,
5334                            driver->inf_path,
5335                            r->inf_path);
5336
5337         r->printer_driver_attributes    = driver->printer_driver_attributes;
5338
5339         result = string_array_from_driver_info(mem_ctx,
5340                                                driver->core_driver_dependencies,
5341                                                &r->core_driver_dependencies,
5342                                                NULL, NULL, 0);
5343         if (!W_ERROR_IS_OK(result)) {
5344                 return result;
5345         }
5346
5347         r->min_inbox_driver_ver_date    = driver->min_inbox_driver_ver_date;
5348         r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5349
5350         return WERR_OK;
5351 }
5352
5353 #if 0 /* disabled until marshalling issues are resolved - gd */
5354 /********************************************************************
5355  ********************************************************************/
5356
5357 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5358                                           struct spoolss_DriverFileInfo *r,
5359                                           const char *cservername,
5360                                           const char *file_name,
5361                                           enum spoolss_DriverFileType file_type,
5362                                           uint32_t file_version)
5363 {
5364         r->file_name    = talloc_asprintf(mem_ctx, "\\\\%s%s",
5365                                           cservername, file_name);
5366         W_ERROR_HAVE_NO_MEMORY(r->file_name);
5367         r->file_type    = file_type;
5368         r->file_version = file_version;
5369
5370         return WERR_OK;
5371 }
5372
5373 /********************************************************************
5374  ********************************************************************/
5375
5376 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5377                                                  const struct spoolss_DriverInfo8 *driver,
5378                                                  const char *cservername,
5379                                                  struct spoolss_DriverFileInfo **info_p,
5380                                                  uint32_t *count_p)
5381 {
5382         struct spoolss_DriverFileInfo *info = NULL;
5383         uint32_t count = 0;
5384         WERROR result;
5385         uint32_t i;
5386
5387         *info_p = NULL;
5388         *count_p = 0;
5389
5390         if (strlen(driver->driver_path)) {
5391                 info = talloc_realloc(mem_ctx, info,
5392                                             struct spoolss_DriverFileInfo,
5393                                             count + 1);
5394                 W_ERROR_HAVE_NO_MEMORY(info);
5395                 result = fill_spoolss_DriverFileInfo(info,
5396                                                      &info[count],
5397                                                      cservername,
5398                                                      driver->driver_path,
5399                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5400                                                      0);
5401                 W_ERROR_NOT_OK_RETURN(result);
5402                 count++;
5403         }
5404
5405         if (strlen(driver->config_file)) {
5406                 info = talloc_realloc(mem_ctx, info,
5407                                             struct spoolss_DriverFileInfo,
5408                                             count + 1);
5409                 W_ERROR_HAVE_NO_MEMORY(info);
5410                 result = fill_spoolss_DriverFileInfo(info,
5411                                                      &info[count],
5412                                                      cservername,
5413                                                      driver->config_file,
5414                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5415                                                      0);
5416                 W_ERROR_NOT_OK_RETURN(result);
5417                 count++;
5418         }
5419
5420         if (strlen(driver->data_file)) {
5421                 info = talloc_realloc(mem_ctx, info,
5422                                             struct spoolss_DriverFileInfo,
5423                                             count + 1);
5424                 W_ERROR_HAVE_NO_MEMORY(info);
5425                 result = fill_spoolss_DriverFileInfo(info,
5426                                                      &info[count],
5427                                                      cservername,
5428                                                      driver->data_file,
5429                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
5430                                                      0);
5431                 W_ERROR_NOT_OK_RETURN(result);
5432                 count++;
5433         }
5434
5435         if (strlen(driver->help_file)) {
5436                 info = talloc_realloc(mem_ctx, info,
5437                                             struct spoolss_DriverFileInfo,
5438                                             count + 1);
5439                 W_ERROR_HAVE_NO_MEMORY(info);
5440                 result = fill_spoolss_DriverFileInfo(info,
5441                                                      &info[count],
5442                                                      cservername,
5443                                                      driver->help_file,
5444                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
5445                                                      0);
5446                 W_ERROR_NOT_OK_RETURN(result);
5447                 count++;
5448         }
5449
5450         for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5451                 info = talloc_realloc(mem_ctx, info,
5452                                             struct spoolss_DriverFileInfo,
5453                                             count + 1);
5454                 W_ERROR_HAVE_NO_MEMORY(info);
5455                 result = fill_spoolss_DriverFileInfo(info,
5456                                                      &info[count],
5457                                                      cservername,
5458                                                      driver->dependent_files[i],
5459                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5460                                                      0);
5461                 W_ERROR_NOT_OK_RETURN(result);
5462                 count++;
5463         }
5464
5465         *info_p = info;
5466         *count_p = count;
5467
5468         return WERR_OK;
5469 }
5470
5471 /********************************************************************
5472  * fill a spoolss_DriverInfo101 struct
5473  ********************************************************************/
5474
5475 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5476                                           struct spoolss_DriverInfo101 *r,
5477                                           const struct spoolss_DriverInfo8 *driver,
5478                                           const char *servername)
5479 {
5480         const char *cservername = canon_servername(servername);
5481         WERROR result;
5482
5483         r->version              = driver->version;
5484
5485         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5486         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5487         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5488         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5489
5490         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5491                                                     cservername,
5492                                                     &r->file_info,
5493                                                     &r->file_count);
5494         if (!W_ERROR_IS_OK(result)) {
5495                 return result;
5496         }
5497
5498         FILL_DRIVER_STRING(mem_ctx,
5499                            driver->monitor_name,
5500                            r->monitor_name);
5501
5502         FILL_DRIVER_STRING(mem_ctx,
5503                            driver->default_datatype,
5504                            r->default_datatype);
5505
5506         result = string_array_from_driver_info(mem_ctx,
5507                                                driver->previous_names,
5508                                                &r->previous_names,
5509                                                NULL, NULL, 0);
5510         if (!W_ERROR_IS_OK(result)) {
5511                 return result;
5512         }
5513
5514         r->driver_date          = driver->driver_date;
5515         r->driver_version       = driver->driver_version;
5516
5517         FILL_DRIVER_STRING(mem_ctx,
5518                            driver->manufacturer_name,
5519                            r->manufacturer_name);
5520         FILL_DRIVER_STRING(mem_ctx,
5521                            driver->manufacturer_url,
5522                            r->manufacturer_url);
5523         FILL_DRIVER_STRING(mem_ctx,
5524                            driver->hardware_id,
5525                            r->hardware_id);
5526         FILL_DRIVER_STRING(mem_ctx,
5527                            driver->provider,
5528                            r->provider);
5529
5530         return WERR_OK;
5531 }
5532 #endif
5533 /********************************************************************
5534  ********************************************************************/
5535
5536 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5537                                                   const struct auth_session_info *session_info,
5538                                                   struct messaging_context *msg_ctx,
5539                                                   uint32_t level,
5540                                                   union spoolss_DriverInfo *r,
5541                                                   int snum,
5542                                                   const char *servername,
5543                                                   const char *architecture,
5544                                                   uint32_t version)
5545 {
5546         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5547         struct spoolss_DriverInfo8 *driver;
5548         WERROR result;
5549         struct dcerpc_binding_handle *b;
5550         TALLOC_CTX *tmp_ctx = NULL;
5551
5552         if (level == 101) {
5553                 return WERR_UNKNOWN_LEVEL;
5554         }
5555
5556         tmp_ctx = talloc_new(mem_ctx);
5557         if (!tmp_ctx) {
5558                 return WERR_NOMEM;
5559         }
5560
5561         result = winreg_printer_binding_handle(tmp_ctx,
5562                                                session_info,
5563                                                msg_ctx,
5564                                                &b);
5565         if (!W_ERROR_IS_OK(result)) {
5566                 goto done;
5567         }
5568
5569         result = winreg_get_printer(tmp_ctx, b,
5570                                     lp_const_servicename(snum),
5571                                     &pinfo2);
5572
5573         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5574                 win_errstr(result)));
5575
5576         if (!W_ERROR_IS_OK(result)) {
5577                 result = WERR_INVALID_PRINTER_NAME;
5578                 goto done;
5579         }
5580
5581         result = winreg_get_driver(tmp_ctx, b,
5582                                    architecture,
5583                                    pinfo2->drivername, version, &driver);
5584
5585         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5586                 win_errstr(result)));
5587
5588         if (!W_ERROR_IS_OK(result)) {
5589                 /*
5590                  * Is this a W2k client ?
5591                  */
5592
5593                 if (version < 3) {
5594                         result = WERR_UNKNOWN_PRINTER_DRIVER;
5595                         goto done;
5596                 }
5597
5598                 /* Yes - try again with a WinNT driver. */
5599                 version = 2;
5600                 result = winreg_get_driver(tmp_ctx, b,
5601                                            architecture,
5602                                            pinfo2->drivername,
5603                                            version, &driver);
5604                 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5605                         win_errstr(result)));
5606                 if (!W_ERROR_IS_OK(result)) {
5607                         result = WERR_UNKNOWN_PRINTER_DRIVER;
5608                         goto done;
5609                 }
5610         }
5611
5612         /* these are allocated on mem_ctx and not tmp_ctx because they are
5613          * the 'return value' and need to utlive this call */
5614         switch (level) {
5615         case 1:
5616                 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5617                 break;
5618         case 2:
5619                 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5620                 break;
5621         case 3:
5622                 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5623                 break;
5624         case 4:
5625                 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5626                 break;
5627         case 5:
5628                 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5629                 break;
5630         case 6:
5631                 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5632                 break;
5633         case 8:
5634                 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5635                 break;
5636 #if 0 /* disabled until marshalling issues are resolved - gd */
5637         case 101:
5638                 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5639                 break;
5640 #endif
5641         default:
5642                 result = WERR_UNKNOWN_LEVEL;
5643                 break;
5644         }
5645
5646 done:
5647         talloc_free(tmp_ctx);
5648         return result;
5649 }
5650
5651 /****************************************************************
5652  _spoolss_GetPrinterDriver2
5653 ****************************************************************/
5654
5655 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5656                                   struct spoolss_GetPrinterDriver2 *r)
5657 {
5658         struct printer_handle *printer;
5659         WERROR result;
5660
5661         int snum;
5662
5663         /* that's an [in out] buffer */
5664
5665         if (!r->in.buffer && (r->in.offered != 0)) {
5666                 return WERR_INVALID_PARAM;
5667         }
5668
5669         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5670
5671         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5672                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5673                 return WERR_INVALID_PRINTER_NAME;
5674         }
5675
5676         *r->out.needed = 0;
5677         *r->out.server_major_version = 0;
5678         *r->out.server_minor_version = 0;
5679
5680         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5681                 return WERR_BADFID;
5682         }
5683
5684         result = construct_printer_driver_info_level(p->mem_ctx,
5685                                                      get_session_info_system(),
5686                                                      p->msg_ctx,
5687                                                      r->in.level, r->out.info,
5688                                                      snum, printer->servername,
5689                                                      r->in.architecture,
5690                                                      r->in.client_major_version);
5691         if (!W_ERROR_IS_OK(result)) {
5692                 TALLOC_FREE(r->out.info);
5693                 return result;
5694         }
5695
5696         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5697                                                r->out.info, r->in.level);
5698         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5699
5700         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5701 }
5702
5703
5704 /****************************************************************
5705  _spoolss_StartPagePrinter
5706 ****************************************************************/
5707
5708 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5709                                  struct spoolss_StartPagePrinter *r)
5710 {
5711         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5712
5713         if (!Printer) {
5714                 DEBUG(3,("_spoolss_StartPagePrinter: "
5715                         "Error in startpageprinter printer handle\n"));
5716                 return WERR_BADFID;
5717         }
5718
5719         Printer->page_started = true;
5720         return WERR_OK;
5721 }
5722
5723 /****************************************************************
5724  _spoolss_EndPagePrinter
5725 ****************************************************************/
5726
5727 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5728                                struct spoolss_EndPagePrinter *r)
5729 {
5730         int snum;
5731
5732         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5733
5734         if (!Printer) {
5735                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5736                         OUR_HANDLE(r->in.handle)));
5737                 return WERR_BADFID;
5738         }
5739
5740         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5741                 return WERR_BADFID;
5742
5743         Printer->page_started = false;
5744         print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5745
5746         return WERR_OK;
5747 }
5748
5749 /****************************************************************
5750  _spoolss_StartDocPrinter
5751 ****************************************************************/
5752
5753 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5754                                 struct spoolss_StartDocPrinter *r)
5755 {
5756         struct spoolss_DocumentInfo1 *info_1;
5757         int snum;
5758         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5759         WERROR werr;
5760         char *rhost;
5761         int rc;
5762
5763         if (!Printer) {
5764                 DEBUG(2,("_spoolss_StartDocPrinter: "
5765                         "Invalid handle (%s:%u:%u)\n",
5766                         OUR_HANDLE(r->in.handle)));
5767                 return WERR_BADFID;
5768         }
5769
5770         if (Printer->jobid) {
5771                 DEBUG(2, ("_spoolss_StartDocPrinter: "
5772                           "StartDocPrinter called twice! "
5773                           "(existing jobid = %d)\n", Printer->jobid));
5774                 return WERR_INVALID_HANDLE;
5775         }
5776
5777         if (r->in.level != 1) {
5778                 return WERR_UNKNOWN_LEVEL;
5779         }
5780
5781         info_1 = r->in.info.info1;
5782
5783         /*
5784          * a nice thing with NT is it doesn't listen to what you tell it.
5785          * when asked to send _only_ RAW datas, it tries to send datas
5786          * in EMF format.
5787          *
5788          * So I add checks like in NT Server ...
5789          */
5790
5791         if (info_1->datatype) {
5792                 if (strcmp(info_1->datatype, "RAW") != 0) {
5793                         *r->out.job_id = 0;
5794                         return WERR_INVALID_DATATYPE;
5795                 }
5796         }
5797
5798         /* get the share number of the printer */
5799         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5800                 return WERR_BADFID;
5801         }
5802
5803         rc = get_remote_hostname(p->remote_address,
5804                                  &rhost,
5805                                  p->mem_ctx);
5806         if (rc < 0) {
5807                 return WERR_NOMEM;
5808         }
5809         if (strequal(rhost,"UNKNOWN")) {
5810                 rhost = tsocket_address_inet_addr_string(p->remote_address,
5811                                                          p->mem_ctx);
5812                 if (rhost == NULL) {
5813                         return WERR_NOMEM;
5814                 }
5815         }
5816
5817         werr = print_job_start(p->session_info,
5818                                p->msg_ctx,
5819                                rhost,
5820                                snum,
5821                                info_1->document_name,
5822                                info_1->output_file,
5823                                Printer->devmode,
5824                                &Printer->jobid);
5825
5826         /* An error occured in print_job_start() so return an appropriate
5827            NT error code. */
5828
5829         if (!W_ERROR_IS_OK(werr)) {
5830                 return werr;
5831         }
5832
5833         Printer->document_started = true;
5834         *r->out.job_id = Printer->jobid;
5835
5836         return WERR_OK;
5837 }
5838
5839 /****************************************************************
5840  _spoolss_EndDocPrinter
5841 ****************************************************************/
5842
5843 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5844                               struct spoolss_EndDocPrinter *r)
5845 {
5846         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5847         NTSTATUS status;
5848         int snum;
5849
5850         if (!Printer) {
5851                 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5852                         OUR_HANDLE(r->in.handle)));
5853                 return WERR_BADFID;
5854         }
5855
5856         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5857                 return WERR_BADFID;
5858         }
5859
5860         Printer->document_started = false;
5861         status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5862         if (!NT_STATUS_IS_OK(status)) {
5863                 DEBUG(2, ("_spoolss_EndDocPrinter: "
5864                           "print_job_end failed [%s]\n",
5865                           nt_errstr(status)));
5866         }
5867
5868         Printer->jobid = 0;
5869         return ntstatus_to_werror(status);
5870 }
5871
5872 /****************************************************************
5873  _spoolss_WritePrinter
5874 ****************************************************************/
5875
5876 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5877                              struct spoolss_WritePrinter *r)
5878 {
5879         ssize_t buffer_written;
5880         int snum;
5881         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5882
5883         if (!Printer) {
5884                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5885                         OUR_HANDLE(r->in.handle)));
5886                 *r->out.num_written = r->in._data_size;
5887                 return WERR_BADFID;
5888         }
5889
5890         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5891                 return WERR_BADFID;
5892
5893         /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5894         buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5895                                                    snum, Printer->jobid,
5896                                                    (const char *)r->in.data.data,
5897                                                    (size_t)r->in._data_size);
5898         if (buffer_written == (ssize_t)-1) {
5899                 *r->out.num_written = 0;
5900                 if (errno == ENOSPC)
5901                         return WERR_NO_SPOOL_SPACE;
5902                 else
5903                         return WERR_ACCESS_DENIED;
5904         }
5905
5906         *r->out.num_written = r->in._data_size;
5907
5908         return WERR_OK;
5909 }
5910
5911 /********************************************************************
5912  * api_spoolss_getprinter
5913  * called from the spoolss dispatcher
5914  *
5915  ********************************************************************/
5916
5917 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5918                               struct pipes_struct *p)
5919 {
5920         const struct auth_session_info *session_info = p->session_info;
5921         int snum;
5922         WERROR errcode = WERR_BADFUNC;
5923         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5924
5925         if (!Printer) {
5926                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5927                         OUR_HANDLE(handle)));
5928                 return WERR_BADFID;
5929         }
5930
5931         if (!get_printer_snum(p, handle, &snum, NULL))
5932                 return WERR_BADFID;
5933
5934         switch (command) {
5935         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5936                 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
5937                 break;
5938         case SPOOLSS_PRINTER_CONTROL_RESUME:
5939         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5940                 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
5941                 break;
5942         case SPOOLSS_PRINTER_CONTROL_PURGE:
5943                 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
5944                 break;
5945         default:
5946                 return WERR_UNKNOWN_LEVEL;
5947         }
5948
5949         return errcode;
5950 }
5951
5952
5953 /****************************************************************
5954  _spoolss_AbortPrinter
5955  * From MSDN: "Deletes printer's spool file if printer is configured
5956  * for spooling"
5957 ****************************************************************/
5958
5959 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
5960                              struct spoolss_AbortPrinter *r)
5961 {
5962         struct printer_handle   *Printer = find_printer_index_by_hnd(p, r->in.handle);
5963         int             snum;
5964         WERROR          errcode = WERR_OK;
5965
5966         if (!Printer) {
5967                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5968                         OUR_HANDLE(r->in.handle)));
5969                 return WERR_BADFID;
5970         }
5971
5972         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5973                 return WERR_BADFID;
5974
5975         if (!Printer->document_started) {
5976                 return WERR_SPL_NO_STARTDOC;
5977         }
5978
5979         errcode = print_job_delete(p->session_info,
5980                                    p->msg_ctx,
5981                                    snum,
5982                                    Printer->jobid);
5983
5984         return errcode;
5985 }
5986
5987 /********************************************************************
5988  * called by spoolss_api_setprinter
5989  * when updating a printer description
5990  ********************************************************************/
5991
5992 static WERROR update_printer_sec(struct policy_handle *handle,
5993                                  struct pipes_struct *p,
5994                                  struct sec_desc_buf *secdesc_ctr)
5995 {
5996         struct spoolss_security_descriptor *new_secdesc = NULL;
5997         struct spoolss_security_descriptor *old_secdesc = NULL;
5998         const char *printer;
5999         WERROR result;
6000         int snum;
6001         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6002         struct dcerpc_binding_handle *b;
6003         TALLOC_CTX *tmp_ctx = NULL;
6004
6005         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
6006                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6007                          OUR_HANDLE(handle)));
6008
6009                 result = WERR_BADFID;
6010                 goto done;
6011         }
6012
6013         if (secdesc_ctr == NULL) {
6014                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
6015                 result = WERR_INVALID_PARAM;
6016                 goto done;
6017         }
6018         printer = lp_const_servicename(snum);
6019
6020         /* Check the user has permissions to change the security
6021            descriptor.  By experimentation with two NT machines, the user
6022            requires Full Access to the printer to change security
6023            information. */
6024
6025         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
6026                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
6027                 result = WERR_ACCESS_DENIED;
6028                 goto done;
6029         }
6030
6031         tmp_ctx = talloc_new(p->mem_ctx);
6032         if (!tmp_ctx) {
6033                 return WERR_NOMEM;
6034         }
6035
6036         result = winreg_printer_binding_handle(tmp_ctx,
6037                                                get_session_info_system(),
6038                                                p->msg_ctx,
6039                                                &b);
6040         if (!W_ERROR_IS_OK(result)) {
6041                 goto done;
6042         }
6043
6044         /* NT seems to like setting the security descriptor even though
6045            nothing may have actually changed. */
6046         result = winreg_get_printer_secdesc(tmp_ctx, b,
6047                                             printer,
6048                                             &old_secdesc);
6049         if (!W_ERROR_IS_OK(result)) {
6050                 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
6051                 result = WERR_BADFID;
6052                 goto done;
6053         }
6054
6055         if (DEBUGLEVEL >= 10) {
6056                 struct security_acl *the_acl;
6057                 int i;
6058
6059                 the_acl = old_secdesc->dacl;
6060                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6061                            printer, the_acl->num_aces));
6062
6063                 for (i = 0; i < the_acl->num_aces; i++) {
6064                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6065                                            &the_acl->aces[i].trustee),
6066                                   the_acl->aces[i].access_mask));
6067                 }
6068
6069                 the_acl = secdesc_ctr->sd->dacl;
6070
6071                 if (the_acl) {
6072                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6073                                    printer, the_acl->num_aces));
6074
6075                         for (i = 0; i < the_acl->num_aces; i++) {
6076                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6077                                                    &the_acl->aces[i].trustee),
6078                                            the_acl->aces[i].access_mask));
6079                         }
6080                 } else {
6081                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6082                 }
6083         }
6084
6085         new_secdesc = sec_desc_merge(tmp_ctx, secdesc_ctr->sd, old_secdesc);
6086         if (new_secdesc == NULL) {
6087                 result = WERR_NOMEM;
6088                 goto done;
6089         }
6090
6091         if (security_descriptor_equal(new_secdesc, old_secdesc)) {
6092                 result = WERR_OK;
6093                 goto done;
6094         }
6095
6096         result = winreg_set_printer_secdesc(tmp_ctx, b,
6097                                             printer,
6098                                             new_secdesc);
6099
6100 done:
6101         talloc_free(tmp_ctx);
6102         return result;
6103 }
6104
6105 /********************************************************************
6106  Canonicalize printer info from a client
6107  ********************************************************************/
6108
6109 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
6110                              struct spoolss_SetPrinterInfo2 *info2,
6111                              int snum)
6112 {
6113         fstring printername;
6114         const char *p;
6115
6116         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6117                 "portname=%s drivername=%s comment=%s location=%s\n",
6118                 info2->servername, info2->printername, info2->sharename,
6119                 info2->portname, info2->drivername, info2->comment,
6120                 info2->location));
6121
6122         /* we force some elements to "correct" values */
6123         info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
6124         if (info2->servername == NULL) {
6125                 return false;
6126         }
6127         info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6128         if (info2->sharename == NULL) {
6129                 return false;
6130         }
6131
6132         /* check to see if we allow printername != sharename */
6133         if (lp_force_printername(snum)) {
6134                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6135                                         lp_netbios_name(), info2->sharename);
6136         } else {
6137                 /* make sure printername is in \\server\printername format */
6138                 fstrcpy(printername, info2->printername);
6139                 p = printername;
6140                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6141                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6142                                 p++;
6143                 }
6144
6145                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6146                                         lp_netbios_name(), p);
6147         }
6148         if (info2->printername == NULL) {
6149                 return false;
6150         }
6151
6152         info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6153         info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6154
6155         return true;
6156 }
6157
6158 /****************************************************************************
6159 ****************************************************************************/
6160
6161 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6162 {
6163         char *cmd = lp_addport_cmd();
6164         char *command = NULL;
6165         int ret;
6166         bool is_print_op = false;
6167
6168         if ( !*cmd ) {
6169                 return WERR_ACCESS_DENIED;
6170         }
6171
6172         command = talloc_asprintf(ctx,
6173                         "%s \"%s\" \"%s\"", cmd, portname, uri );
6174         if (!command) {
6175                 return WERR_NOMEM;
6176         }
6177
6178         if ( token )
6179                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6180
6181         DEBUG(10,("Running [%s]\n", command));
6182
6183         /********* BEGIN SePrintOperatorPrivilege **********/
6184
6185         if ( is_print_op )
6186                 become_root();
6187
6188         ret = smbrun(command, NULL);
6189
6190         if ( is_print_op )
6191                 unbecome_root();
6192
6193         /********* END SePrintOperatorPrivilege **********/
6194
6195         DEBUGADD(10,("returned [%d]\n", ret));
6196
6197         TALLOC_FREE(command);
6198
6199         if ( ret != 0 ) {
6200                 return WERR_ACCESS_DENIED;
6201         }
6202
6203         return WERR_OK;
6204 }
6205
6206 /****************************************************************************
6207 ****************************************************************************/
6208
6209 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6210                              struct spoolss_SetPrinterInfo2 *info2,
6211                              const char *remote_machine,
6212                              struct messaging_context *msg_ctx)
6213 {
6214         char *cmd = lp_addprinter_cmd();
6215         char **qlines;
6216         char *command = NULL;
6217         int numlines;
6218         int ret;
6219         int fd;
6220         bool is_print_op = false;
6221
6222         if (!remote_machine) {
6223                 return false;
6224         }
6225
6226         command = talloc_asprintf(ctx,
6227                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6228                         cmd, info2->printername, info2->sharename,
6229                         info2->portname, info2->drivername,
6230                         info2->location, info2->comment, remote_machine);
6231         if (!command) {
6232                 return false;
6233         }
6234
6235         if ( token )
6236                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6237
6238         DEBUG(10,("Running [%s]\n", command));
6239
6240         /********* BEGIN SePrintOperatorPrivilege **********/
6241
6242         if ( is_print_op )
6243                 become_root();
6244
6245         if ( (ret = smbrun(command, &fd)) == 0 ) {
6246                 /* Tell everyone we updated smb.conf. */
6247                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6248         }
6249
6250         if ( is_print_op )
6251                 unbecome_root();
6252
6253         /********* END SePrintOperatorPrivilege **********/
6254
6255         DEBUGADD(10,("returned [%d]\n", ret));
6256
6257         TALLOC_FREE(command);
6258
6259         if ( ret != 0 ) {
6260                 if (fd != -1)
6261                         close(fd);
6262                 return false;
6263         }
6264
6265         /* reload our services immediately */
6266         become_root();
6267         reload_services(msg_ctx, -1, false);
6268         unbecome_root();
6269
6270         numlines = 0;
6271         /* Get lines and convert them back to dos-codepage */
6272         qlines = fd_lines_load(fd, &numlines, 0, NULL);
6273         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6274         close(fd);
6275
6276         /* Set the portname to what the script says the portname should be. */
6277         /* but don't require anything to be return from the script exit a good error code */
6278
6279         if (numlines) {
6280                 /* Set the portname to what the script says the portname should be. */
6281                 info2->portname = talloc_strdup(ctx, qlines[0]);
6282                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6283         }
6284
6285         TALLOC_FREE(qlines);
6286         return true;
6287 }
6288
6289 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6290                                const struct auth_session_info *session_info,
6291                                struct messaging_context *msg_ctx,
6292                                int snum,
6293                                struct spoolss_SetPrinterInfo2 *printer,
6294                                struct spoolss_PrinterInfo2 *old_printer)
6295 {
6296         bool force_update = (old_printer == NULL);
6297         const char *dnsdomname;
6298         const char *longname;
6299         const char *uncname;
6300         const char *spooling;
6301         DATA_BLOB buffer;
6302         WERROR result = WERR_OK;
6303         struct dcerpc_binding_handle *b;
6304         TALLOC_CTX *tmp_ctx;
6305
6306         tmp_ctx = talloc_new(mem_ctx);
6307         if (!tmp_ctx) {
6308                 return WERR_NOMEM;
6309         }
6310
6311         result = winreg_printer_binding_handle(tmp_ctx,
6312                                                session_info,
6313                                                msg_ctx,
6314                                                &b);
6315         if (!W_ERROR_IS_OK(result)) {
6316                 goto done;
6317         }
6318
6319         if (force_update || !strequal(printer->drivername, old_printer->drivername)) {
6320                 push_reg_sz(tmp_ctx, &buffer, printer->drivername);
6321                 winreg_set_printer_dataex(tmp_ctx, b,
6322                                           printer->sharename,
6323                                           SPOOL_DSSPOOLER_KEY,
6324                                           SPOOL_REG_DRIVERNAME,
6325                                           REG_SZ,
6326                                           buffer.data,
6327                                           buffer.length);
6328
6329                 if (!force_update) {
6330                         DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6331                                 printer->drivername));
6332
6333                         notify_printer_driver(server_event_context(), msg_ctx,
6334                                               snum, printer->drivername ?
6335                                               printer->drivername : "");
6336                 }
6337         }
6338
6339         if (force_update || !strequal(printer->comment, old_printer->comment)) {
6340                 push_reg_sz(tmp_ctx, &buffer, printer->comment);
6341                 winreg_set_printer_dataex(tmp_ctx, b,
6342                                           printer->sharename,
6343                                           SPOOL_DSSPOOLER_KEY,
6344                                           SPOOL_REG_DESCRIPTION,
6345                                           REG_SZ,
6346                                           buffer.data,
6347                                           buffer.length);
6348
6349                 if (!force_update) {
6350                         notify_printer_comment(server_event_context(), msg_ctx,
6351                                                snum, printer->comment ?
6352                                                printer->comment : "");
6353                 }
6354         }
6355
6356         if (force_update || !strequal(printer->sharename, old_printer->sharename)) {
6357                 push_reg_sz(tmp_ctx, &buffer, printer->sharename);
6358                 winreg_set_printer_dataex(tmp_ctx, b,
6359                                           printer->sharename,
6360                                           SPOOL_DSSPOOLER_KEY,
6361                                           SPOOL_REG_PRINTSHARENAME,
6362                                           REG_SZ,
6363                                           buffer.data,
6364                                           buffer.length);
6365
6366                 if (!force_update) {
6367                         notify_printer_sharename(server_event_context(),
6368                                                  msg_ctx,
6369                                                  snum, printer->sharename ?
6370                                                  printer->sharename : "");
6371                 }
6372         }
6373
6374         if (force_update || !strequal(printer->printername, old_printer->printername)) {
6375                 const char *p;
6376
6377                 p = strrchr(printer->printername, '\\' );
6378                 if (p != NULL) {
6379                         p++;
6380                 } else {
6381                         p = printer->printername;
6382                 }
6383
6384                 push_reg_sz(tmp_ctx, &buffer, p);
6385                 winreg_set_printer_dataex(tmp_ctx, b,
6386                                           printer->sharename,
6387                                           SPOOL_DSSPOOLER_KEY,
6388                                           SPOOL_REG_PRINTERNAME,
6389                                           REG_SZ,
6390                                           buffer.data,
6391                                           buffer.length);
6392
6393                 if (!force_update) {
6394                         notify_printer_printername(server_event_context(),
6395                                                    msg_ctx, snum, p ? p : "");
6396                 }
6397         }
6398
6399         if (force_update || !strequal(printer->portname, old_printer->portname)) {
6400                 push_reg_sz(tmp_ctx, &buffer, printer->portname);
6401                 winreg_set_printer_dataex(tmp_ctx, b,
6402                                           printer->sharename,
6403                                           SPOOL_DSSPOOLER_KEY,
6404                                           SPOOL_REG_PORTNAME,
6405                                           REG_SZ,
6406                                           buffer.data,
6407                                           buffer.length);
6408
6409                 if (!force_update) {
6410                         notify_printer_port(server_event_context(),
6411                                             msg_ctx, snum, printer->portname ?
6412                                             printer->portname : "");
6413                 }
6414         }
6415
6416         if (force_update || !strequal(printer->location, old_printer->location)) {
6417                 push_reg_sz(tmp_ctx, &buffer, printer->location);
6418                 winreg_set_printer_dataex(tmp_ctx, b,
6419                                           printer->sharename,
6420                                           SPOOL_DSSPOOLER_KEY,
6421                                           SPOOL_REG_LOCATION,
6422                                           REG_SZ,
6423                                           buffer.data,
6424                                           buffer.length);
6425
6426                 if (!force_update) {
6427                         notify_printer_location(server_event_context(),
6428                                                 msg_ctx, snum,
6429                                                 printer->location ?
6430                                                 printer->location : "");
6431                 }
6432         }
6433
6434         if (force_update || !strequal(printer->sepfile, old_printer->sepfile)) {
6435                 push_reg_sz(tmp_ctx, &buffer, printer->sepfile);
6436                 winreg_set_printer_dataex(tmp_ctx, b,
6437                                           printer->sharename,
6438                                           SPOOL_DSSPOOLER_KEY,
6439                                           SPOOL_REG_PRINTSEPARATORFILE,
6440                                           REG_SZ,
6441                                           buffer.data,
6442                                           buffer.length);
6443
6444                 if (!force_update) {
6445                         notify_printer_sepfile(server_event_context(),
6446                                                msg_ctx, snum,
6447                                                printer->sepfile ?
6448                                                printer->sepfile : "");
6449                 }
6450         }
6451
6452         if (force_update || printer->starttime != old_printer->starttime) {
6453                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6454                 SIVAL(buffer.data, 0, printer->starttime);
6455                 winreg_set_printer_dataex(tmp_ctx, b,
6456                                           printer->sharename,
6457                                           SPOOL_DSSPOOLER_KEY,
6458                                           SPOOL_REG_PRINTSTARTTIME,
6459                                           REG_DWORD,
6460                                           buffer.data,
6461                                           buffer.length);
6462         }
6463
6464         if (force_update || printer->untiltime != old_printer->untiltime) {
6465                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6466                 SIVAL(buffer.data, 0, printer->untiltime);
6467                 winreg_set_printer_dataex(tmp_ctx, b,
6468                                           printer->sharename,
6469                                           SPOOL_DSSPOOLER_KEY,
6470                                           SPOOL_REG_PRINTENDTIME,
6471                                           REG_DWORD,
6472                                           buffer.data,
6473                                           buffer.length);
6474         }
6475
6476         if (force_update || printer->priority != old_printer->priority) {
6477                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6478                 SIVAL(buffer.data, 0, printer->priority);
6479                 winreg_set_printer_dataex(tmp_ctx, b,
6480                                           printer->sharename,
6481                                           SPOOL_DSSPOOLER_KEY,
6482                                           SPOOL_REG_PRIORITY,
6483                                           REG_DWORD,
6484                                           buffer.data,
6485                                           buffer.length);
6486         }
6487
6488         if (force_update || printer->attributes != old_printer->attributes) {
6489                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6490                 SIVAL(buffer.data, 0, (printer->attributes &
6491                                        PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6492                 winreg_set_printer_dataex(tmp_ctx, b,
6493                                           printer->sharename,
6494                                           SPOOL_DSSPOOLER_KEY,
6495                                           SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6496                                           REG_DWORD,
6497                                           buffer.data,
6498                                           buffer.length);
6499
6500                 switch (printer->attributes & 0x3) {
6501                         case 0:
6502                                 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6503                                 break;
6504                         case 1:
6505                                 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6506                                 break;
6507                         case 2:
6508                                 spooling = SPOOL_REGVAL_PRINTDIRECT;
6509                                 break;
6510                         default:
6511                                 spooling = "unknown";
6512                 }
6513                 push_reg_sz(tmp_ctx, &buffer, spooling);
6514                 winreg_set_printer_dataex(tmp_ctx, b,
6515                                           printer->sharename,
6516                                           SPOOL_DSSPOOLER_KEY,
6517                                           SPOOL_REG_PRINTSPOOLING,
6518                                           REG_SZ,
6519                                           buffer.data,
6520                                           buffer.length);
6521         }
6522
6523         push_reg_sz(tmp_ctx, &buffer, lp_netbios_name());
6524         winreg_set_printer_dataex(tmp_ctx, b,
6525                                   printer->sharename,
6526                                   SPOOL_DSSPOOLER_KEY,
6527                                   SPOOL_REG_SHORTSERVERNAME,
6528                                   REG_SZ,
6529                                   buffer.data,
6530                                   buffer.length);
6531
6532         dnsdomname = get_mydnsfullname();
6533         if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6534                 longname = talloc_strdup(tmp_ctx, dnsdomname);
6535         } else {
6536                 longname = talloc_strdup(tmp_ctx, lp_netbios_name());
6537         }
6538         if (longname == NULL) {
6539                 result = WERR_NOMEM;
6540                 goto done;
6541         }
6542
6543         push_reg_sz(tmp_ctx, &buffer, longname);
6544         winreg_set_printer_dataex(tmp_ctx, b,
6545                                   printer->sharename,
6546                                   SPOOL_DSSPOOLER_KEY,
6547                                   SPOOL_REG_SERVERNAME,
6548                                   REG_SZ,
6549                                   buffer.data,
6550                                   buffer.length);
6551
6552         uncname = talloc_asprintf(tmp_ctx, "\\\\%s\\%s",
6553                                   lp_netbios_name(), printer->sharename);
6554         push_reg_sz(tmp_ctx, &buffer, uncname);
6555         winreg_set_printer_dataex(tmp_ctx, b,
6556                                   printer->sharename,
6557                                   SPOOL_DSSPOOLER_KEY,
6558                                   SPOOL_REG_UNCNAME,
6559                                   REG_SZ,
6560                                   buffer.data,
6561                                   buffer.length);
6562
6563 done:
6564         talloc_free(tmp_ctx);
6565         return result;
6566 }
6567
6568 /********************************************************************
6569  * Called by spoolss_api_setprinter
6570  * when updating a printer description.
6571  ********************************************************************/
6572
6573 static WERROR update_printer(struct pipes_struct *p,
6574                              struct policy_handle *handle,
6575                              struct spoolss_SetPrinterInfoCtr *info_ctr,
6576                              struct spoolss_DeviceMode *devmode)
6577 {
6578         uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6579         struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6580         struct spoolss_PrinterInfo2 *old_printer;
6581         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6582         int snum;
6583         WERROR result = WERR_OK;
6584         TALLOC_CTX *tmp_ctx;
6585         struct dcerpc_binding_handle *b;
6586
6587         DEBUG(8,("update_printer\n"));
6588
6589         tmp_ctx = talloc_new(p->mem_ctx);
6590         if (tmp_ctx == NULL) {
6591                 return WERR_NOMEM;
6592         }
6593
6594         if (!Printer) {
6595                 result = WERR_BADFID;
6596                 goto done;
6597         }
6598
6599         if (!get_printer_snum(p, handle, &snum, NULL)) {
6600                 result = WERR_BADFID;
6601                 goto done;
6602         }
6603
6604         result = winreg_printer_binding_handle(tmp_ctx,
6605                                                get_session_info_system(),
6606                                                p->msg_ctx,
6607                                                &b);
6608         if (!W_ERROR_IS_OK(result)) {
6609                 goto done;
6610         }
6611
6612         result = winreg_get_printer(tmp_ctx, b,
6613                                     lp_const_servicename(snum),
6614                                     &old_printer);
6615         if (!W_ERROR_IS_OK(result)) {
6616                 result = WERR_BADFID;
6617                 goto done;
6618         }
6619
6620         /* Do sanity check on the requested changes for Samba */
6621         if (!check_printer_ok(tmp_ctx, printer, snum)) {
6622                 result = WERR_INVALID_PARAM;
6623                 goto done;
6624         }
6625
6626         /* FIXME!!! If the driver has changed we really should verify that
6627            it is installed before doing much else   --jerry */
6628
6629         /* Check calling user has permission to update printer description */
6630         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6631                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6632                 result = WERR_ACCESS_DENIED;
6633                 goto done;
6634         }
6635
6636         /* Call addprinter hook */
6637         /* Check changes to see if this is really needed */
6638
6639         if (*lp_addprinter_cmd() &&
6640                         (!strequal(printer->drivername, old_printer->drivername) ||
6641                          !strequal(printer->comment, old_printer->comment) ||
6642                          !strequal(printer->portname, old_printer->portname) ||
6643                          !strequal(printer->location, old_printer->location)) )
6644         {
6645                 char *raddr;
6646
6647                 raddr = tsocket_address_inet_addr_string(p->remote_address,
6648                                                          p->mem_ctx);
6649                 if (raddr == NULL) {
6650                         return WERR_NOMEM;
6651                 }
6652
6653                 /* add_printer_hook() will call reload_services() */
6654                 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6655                                       printer, raddr,
6656                                       p->msg_ctx)) {
6657                         result = WERR_ACCESS_DENIED;
6658                         goto done;
6659                 }
6660         }
6661
6662         update_dsspooler(tmp_ctx,
6663                          get_session_info_system(),
6664                          p->msg_ctx,
6665                          snum,
6666                          printer,
6667                          old_printer);
6668
6669         printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6670
6671         if (devmode == NULL) {
6672                 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6673         }
6674         result = winreg_update_printer(tmp_ctx, b,
6675                                        printer->sharename,
6676                                        printer_mask,
6677                                        printer,
6678                                        devmode,
6679                                        NULL);
6680
6681 done:
6682         talloc_free(tmp_ctx);
6683
6684         return result;
6685 }
6686
6687 /****************************************************************************
6688 ****************************************************************************/
6689 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6690                                            struct policy_handle *handle,
6691                                            struct spoolss_SetPrinterInfo7 *info7)
6692 {
6693 #ifdef HAVE_ADS
6694         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6695         WERROR result;
6696         int snum;
6697         struct printer_handle *Printer;
6698
6699         if ( lp_security() != SEC_ADS ) {
6700                 return WERR_UNKNOWN_LEVEL;
6701         }
6702
6703         Printer = find_printer_index_by_hnd(p, handle);
6704
6705         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6706
6707         if (!Printer)
6708                 return WERR_BADFID;
6709
6710         if (!get_printer_snum(p, handle, &snum, NULL))
6711                 return WERR_BADFID;
6712
6713         result = winreg_get_printer_internal(p->mem_ctx,
6714                                     get_session_info_system(),
6715                                     p->msg_ctx,
6716                                     lp_servicename(snum),
6717                                     &pinfo2);
6718         if (!W_ERROR_IS_OK(result)) {
6719                 return WERR_BADFID;
6720         }
6721
6722         nt_printer_publish(pinfo2,
6723                            get_session_info_system(),
6724                            p->msg_ctx,
6725                            pinfo2,
6726                            info7->action);
6727
6728         TALLOC_FREE(pinfo2);
6729         return WERR_OK;
6730 #else
6731         return WERR_UNKNOWN_LEVEL;
6732 #endif
6733 }
6734
6735 /********************************************************************
6736  ********************************************************************/
6737
6738 static WERROR update_printer_devmode(struct pipes_struct *p,
6739                                      struct policy_handle *handle,
6740                                      struct spoolss_DeviceMode *devmode)
6741 {
6742         int snum;
6743         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6744         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6745
6746         DEBUG(8,("update_printer_devmode\n"));
6747
6748         if (!Printer) {
6749                 return WERR_BADFID;
6750         }
6751
6752         if (!get_printer_snum(p, handle, &snum, NULL)) {
6753                 return WERR_BADFID;
6754         }
6755
6756         /* Check calling user has permission to update printer description */
6757         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6758                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6759                 return WERR_ACCESS_DENIED;
6760         }
6761
6762         return winreg_update_printer_internal(p->mem_ctx,
6763                                      get_session_info_system(),
6764                                      p->msg_ctx,
6765                                      lp_const_servicename(snum),
6766                                      info2_mask,
6767                                      NULL,
6768                                      devmode,
6769                                      NULL);
6770 }
6771
6772
6773 /****************************************************************
6774  _spoolss_SetPrinter
6775 ****************************************************************/
6776
6777 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6778                            struct spoolss_SetPrinter *r)
6779 {
6780         WERROR result;
6781
6782         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6783
6784         if (!Printer) {
6785                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6786                         OUR_HANDLE(r->in.handle)));
6787                 return WERR_BADFID;
6788         }
6789
6790         /* check the level */
6791         switch (r->in.info_ctr->level) {
6792                 case 0:
6793                         return control_printer(r->in.handle, r->in.command, p);
6794                 case 2:
6795                         result = update_printer(p, r->in.handle,
6796                                                 r->in.info_ctr,
6797                                                 r->in.devmode_ctr->devmode);
6798                         if (!W_ERROR_IS_OK(result))
6799                                 return result;
6800                         if (r->in.secdesc_ctr->sd)
6801                                 result = update_printer_sec(r->in.handle, p,
6802                                                             r->in.secdesc_ctr);
6803                         return result;
6804                 case 3:
6805                         return update_printer_sec(r->in.handle, p,
6806                                                   r->in.secdesc_ctr);
6807                 case 7:
6808                         return publish_or_unpublish_printer(p, r->in.handle,
6809                                                             r->in.info_ctr->info.info7);
6810                 case 8:
6811                         return update_printer_devmode(p, r->in.handle,
6812                                                       r->in.devmode_ctr->devmode);
6813                 default:
6814                         return WERR_UNKNOWN_LEVEL;
6815         }
6816 }
6817
6818 /****************************************************************
6819  _spoolss_FindClosePrinterNotify
6820 ****************************************************************/
6821
6822 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
6823                                        struct spoolss_FindClosePrinterNotify *r)
6824 {
6825         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6826
6827         if (!Printer) {
6828                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6829                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6830                 return WERR_BADFID;
6831         }
6832
6833         if (Printer->notify.cli_chan != NULL &&
6834             Printer->notify.cli_chan->active_connections > 0) {
6835                 int snum = -1;
6836
6837                 if (Printer->printer_type == SPLHND_PRINTER) {
6838                         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6839                                 return WERR_BADFID;
6840                         }
6841                 }
6842
6843                 srv_spoolss_replycloseprinter(snum, Printer);
6844         }
6845
6846         Printer->notify.flags=0;
6847         Printer->notify.options=0;
6848         Printer->notify.localmachine[0]='\0';
6849         Printer->notify.printerlocal=0;
6850         TALLOC_FREE(Printer->notify.option);
6851
6852         return WERR_OK;
6853 }
6854
6855 /****************************************************************
6856  _spoolss_AddJob
6857 ****************************************************************/
6858
6859 WERROR _spoolss_AddJob(struct pipes_struct *p,
6860                        struct spoolss_AddJob *r)
6861 {
6862         if (!r->in.buffer && (r->in.offered != 0)) {
6863                 return WERR_INVALID_PARAM;
6864         }
6865
6866         /* this is what a NT server returns for AddJob. AddJob must fail on
6867          * non-local printers */
6868
6869         if (r->in.level != 1) {
6870                 return WERR_UNKNOWN_LEVEL;
6871         }
6872
6873         return WERR_INVALID_PARAM;
6874 }
6875
6876 /****************************************************************************
6877 fill_job_info1
6878 ****************************************************************************/
6879
6880 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6881                              struct spoolss_JobInfo1 *r,
6882                              const print_queue_struct *queue,
6883                              int position, int snum,
6884                              struct spoolss_PrinterInfo2 *pinfo2)
6885 {
6886         struct tm *t;
6887
6888         t = gmtime(&queue->time);
6889
6890         r->job_id               = queue->job;
6891
6892         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6893         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6894         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
6895         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6896         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6897         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6898         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6899         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6900         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6901         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6902         r->text_status          = talloc_strdup(mem_ctx, "");
6903         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6904
6905         r->status               = nt_printj_status(queue->status);
6906         r->priority             = queue->priority;
6907         r->position             = position;
6908         r->total_pages          = queue->page_count;
6909         r->pages_printed        = 0; /* ??? */
6910
6911         init_systemtime(&r->submitted, t);
6912
6913         return WERR_OK;
6914 }
6915
6916 /****************************************************************************
6917 fill_job_info2
6918 ****************************************************************************/
6919
6920 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6921                              struct spoolss_JobInfo2 *r,
6922                              const print_queue_struct *queue,
6923                              int position, int snum,
6924                              struct spoolss_PrinterInfo2 *pinfo2,
6925                              struct spoolss_DeviceMode *devmode)
6926 {
6927         struct tm *t;
6928
6929         t = gmtime(&queue->time);
6930
6931         r->job_id               = queue->job;
6932
6933         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6934         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6935         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
6936         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6937         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6938         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6939         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6940         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6941         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
6942         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6943         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6944         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6945         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
6946         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6947         r->parameters           = talloc_strdup(mem_ctx, "");
6948         W_ERROR_HAVE_NO_MEMORY(r->parameters);
6949         r->driver_name          = talloc_strdup(mem_ctx, pinfo2->drivername);
6950         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6951
6952         r->devmode              = devmode;
6953
6954         r->text_status          = talloc_strdup(mem_ctx, "");
6955         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6956
6957         r->secdesc              = NULL;
6958
6959         r->status               = nt_printj_status(queue->status);
6960         r->priority             = queue->priority;
6961         r->position             = position;
6962         r->start_time           = 0;
6963         r->until_time           = 0;
6964         r->total_pages          = queue->page_count;
6965         r->size                 = queue->size;
6966         init_systemtime(&r->submitted, t);
6967         r->time                 = 0;
6968         r->pages_printed        = 0; /* ??? */
6969
6970         return WERR_OK;
6971 }
6972
6973 /****************************************************************************
6974 fill_job_info3
6975 ****************************************************************************/
6976
6977 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6978                              struct spoolss_JobInfo3 *r,
6979                              const print_queue_struct *queue,
6980                              const print_queue_struct *next_queue,
6981                              int position, int snum,
6982                              struct spoolss_PrinterInfo2 *pinfo2)
6983 {
6984         r->job_id               = queue->job;
6985         r->next_job_id          = 0;
6986         if (next_queue) {
6987                 r->next_job_id  = next_queue->job;
6988         }
6989         r->reserved             = 0;
6990
6991         return WERR_OK;
6992 }
6993
6994 /****************************************************************************
6995  Enumjobs at level 1.
6996 ****************************************************************************/
6997
6998 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6999                               const print_queue_struct *queue,
7000                               uint32_t num_queues, int snum,
7001                               struct spoolss_PrinterInfo2 *pinfo2,
7002                               union spoolss_JobInfo **info_p,
7003                               uint32_t *count)
7004 {
7005         union spoolss_JobInfo *info;
7006         int i;
7007         WERROR result = WERR_OK;
7008
7009         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7010         W_ERROR_HAVE_NO_MEMORY(info);
7011
7012         *count = num_queues;
7013
7014         for (i=0; i<*count; i++) {
7015                 result = fill_job_info1(info,
7016                                         &info[i].info1,
7017                                         &queue[i],
7018                                         i,
7019                                         snum,
7020                                         pinfo2);
7021                 if (!W_ERROR_IS_OK(result)) {
7022                         goto out;
7023                 }
7024         }
7025
7026  out:
7027         if (!W_ERROR_IS_OK(result)) {
7028                 TALLOC_FREE(info);
7029                 *count = 0;
7030                 return result;
7031         }
7032
7033         *info_p = info;
7034
7035         return WERR_OK;
7036 }
7037
7038 /****************************************************************************
7039  Enumjobs at level 2.
7040 ****************************************************************************/
7041
7042 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
7043                               const print_queue_struct *queue,
7044                               uint32_t num_queues, int snum,
7045                               struct spoolss_PrinterInfo2 *pinfo2,
7046                               union spoolss_JobInfo **info_p,
7047                               uint32_t *count)
7048 {
7049         union spoolss_JobInfo *info;
7050         int i;
7051         WERROR result = WERR_OK;
7052
7053         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7054         W_ERROR_HAVE_NO_MEMORY(info);
7055
7056         *count = num_queues;
7057
7058         for (i=0; i<*count; i++) {
7059                 struct spoolss_DeviceMode *devmode;
7060
7061                 result = spoolss_create_default_devmode(info,
7062                                                         pinfo2->printername,
7063                                                         &devmode);
7064                 if (!W_ERROR_IS_OK(result)) {
7065                         DEBUG(3, ("Can't proceed w/o a devmode!"));
7066                         goto out;
7067                 }
7068
7069                 result = fill_job_info2(info,
7070                                         &info[i].info2,
7071                                         &queue[i],
7072                                         i,
7073                                         snum,
7074                                         pinfo2,
7075                                         devmode);
7076                 if (!W_ERROR_IS_OK(result)) {
7077                         goto out;
7078                 }
7079         }
7080
7081  out:
7082         if (!W_ERROR_IS_OK(result)) {
7083                 TALLOC_FREE(info);
7084                 *count = 0;
7085                 return result;
7086         }
7087
7088         *info_p = info;
7089
7090         return WERR_OK;
7091 }
7092
7093 /****************************************************************************
7094  Enumjobs at level 3.
7095 ****************************************************************************/
7096
7097 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
7098                               const print_queue_struct *queue,
7099                               uint32_t num_queues, int snum,
7100                               struct spoolss_PrinterInfo2 *pinfo2,
7101                               union spoolss_JobInfo **info_p,
7102                               uint32_t *count)
7103 {
7104         union spoolss_JobInfo *info;
7105         int i;
7106         WERROR result = WERR_OK;
7107
7108         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7109         W_ERROR_HAVE_NO_MEMORY(info);
7110
7111         *count = num_queues;
7112
7113         for (i=0; i<*count; i++) {
7114                 const print_queue_struct *next_queue = NULL;
7115
7116                 if (i+1 < *count) {
7117                         next_queue = &queue[i+1];
7118                 }
7119
7120                 result = fill_job_info3(info,
7121                                         &info[i].info3,
7122                                         &queue[i],
7123                                         next_queue,
7124                                         i,
7125                                         snum,
7126                                         pinfo2);
7127                 if (!W_ERROR_IS_OK(result)) {
7128                         goto out;
7129                 }
7130         }
7131
7132  out:
7133         if (!W_ERROR_IS_OK(result)) {
7134                 TALLOC_FREE(info);
7135                 *count = 0;
7136                 return result;
7137         }
7138
7139         *info_p = info;
7140
7141         return WERR_OK;
7142 }
7143
7144 /****************************************************************
7145  _spoolss_EnumJobs
7146 ****************************************************************/
7147
7148 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7149                          struct spoolss_EnumJobs *r)
7150 {
7151         WERROR result;
7152         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7153         int snum;
7154         print_status_struct prt_status;
7155         print_queue_struct *queue = NULL;
7156         uint32_t count;
7157
7158         /* that's an [in out] buffer */
7159
7160         if (!r->in.buffer && (r->in.offered != 0)) {
7161                 return WERR_INVALID_PARAM;
7162         }
7163
7164         DEBUG(4,("_spoolss_EnumJobs\n"));
7165
7166         *r->out.needed = 0;
7167         *r->out.count = 0;
7168         *r->out.info = NULL;
7169
7170         /* lookup the printer snum and tdb entry */
7171
7172         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7173                 return WERR_BADFID;
7174         }
7175
7176         result = winreg_get_printer_internal(p->mem_ctx,
7177                                     get_session_info_system(),
7178                                     p->msg_ctx,
7179                                     lp_const_servicename(snum),
7180                                     &pinfo2);
7181         if (!W_ERROR_IS_OK(result)) {
7182                 return result;
7183         }
7184
7185         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7186         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7187                 count, prt_status.status, prt_status.message));
7188
7189         if (count == 0) {
7190                 SAFE_FREE(queue);
7191                 TALLOC_FREE(pinfo2);
7192                 return WERR_OK;
7193         }
7194
7195         switch (r->in.level) {
7196         case 1:
7197                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7198                                          pinfo2, r->out.info, r->out.count);
7199                 break;
7200         case 2:
7201                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7202                                          pinfo2, r->out.info, r->out.count);
7203                 break;
7204         case 3:
7205                 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7206                                          pinfo2, r->out.info, r->out.count);
7207                 break;
7208         default:
7209                 result = WERR_UNKNOWN_LEVEL;
7210                 break;
7211         }
7212
7213         SAFE_FREE(queue);
7214         TALLOC_FREE(pinfo2);
7215
7216         if (!W_ERROR_IS_OK(result)) {
7217                 return result;
7218         }
7219
7220         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7221                                                      spoolss_EnumJobs,
7222                                                      *r->out.info, r->in.level,
7223                                                      *r->out.count);
7224         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7225         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7226
7227         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7228 }
7229
7230 /****************************************************************
7231  _spoolss_ScheduleJob
7232 ****************************************************************/
7233
7234 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7235                             struct spoolss_ScheduleJob *r)
7236 {
7237         return WERR_OK;
7238 }
7239
7240 /****************************************************************
7241 ****************************************************************/
7242
7243 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7244                                struct messaging_context *msg_ctx,
7245                                const char *printer_name,
7246                                uint32_t job_id,
7247                                struct spoolss_SetJobInfo1 *r)
7248 {
7249         char *old_doc_name;
7250
7251         if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7252                 return WERR_BADFID;
7253         }
7254
7255         if (strequal(old_doc_name, r->document_name)) {
7256                 return WERR_OK;
7257         }
7258
7259         if (!print_job_set_name(server_event_context(), msg_ctx,
7260                                 printer_name, job_id, r->document_name)) {
7261                 return WERR_BADFID;
7262         }
7263
7264         return WERR_OK;
7265 }
7266
7267 /****************************************************************
7268  _spoolss_SetJob
7269 ****************************************************************/
7270
7271 WERROR _spoolss_SetJob(struct pipes_struct *p,
7272                        struct spoolss_SetJob *r)
7273 {
7274         const struct auth_session_info *session_info = p->session_info;
7275         int snum;
7276         WERROR errcode = WERR_BADFUNC;
7277
7278         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7279                 return WERR_BADFID;
7280         }
7281
7282         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7283                 return WERR_INVALID_PRINTER_NAME;
7284         }
7285
7286         switch (r->in.command) {
7287         case SPOOLSS_JOB_CONTROL_CANCEL:
7288         case SPOOLSS_JOB_CONTROL_DELETE:
7289                 errcode = print_job_delete(session_info, p->msg_ctx,
7290                                            snum, r->in.job_id);
7291                 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7292                         errcode = WERR_OK;
7293                 }
7294                 break;
7295         case SPOOLSS_JOB_CONTROL_PAUSE:
7296                 if (print_job_pause(session_info, p->msg_ctx,
7297                                     snum, r->in.job_id, &errcode)) {
7298                         errcode = WERR_OK;
7299                 }
7300                 break;
7301         case SPOOLSS_JOB_CONTROL_RESTART:
7302         case SPOOLSS_JOB_CONTROL_RESUME:
7303                 if (print_job_resume(session_info, p->msg_ctx,
7304                                      snum, r->in.job_id, &errcode)) {
7305                         errcode = WERR_OK;
7306                 }
7307                 break;
7308         case 0:
7309                 errcode = WERR_OK;
7310                 break;
7311         default:
7312                 return WERR_UNKNOWN_LEVEL;
7313         }
7314
7315         if (!W_ERROR_IS_OK(errcode)) {
7316                 return errcode;
7317         }
7318
7319         if (r->in.ctr == NULL) {
7320                 return errcode;
7321         }
7322
7323         switch (r->in.ctr->level) {
7324         case 1:
7325                 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7326                                            lp_const_servicename(snum),
7327                                            r->in.job_id,
7328                                            r->in.ctr->info.info1);
7329                 break;
7330         case 2:
7331         case 3:
7332         case 4:
7333         default:
7334                 return WERR_UNKNOWN_LEVEL;
7335         }
7336
7337         return errcode;
7338 }
7339
7340 /****************************************************************************
7341  Enumerates all printer drivers by level and architecture.
7342 ****************************************************************************/
7343
7344 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7345                                                        const struct auth_session_info *session_info,
7346                                                        struct messaging_context *msg_ctx,
7347                                                        const char *servername,
7348                                                        const char *architecture,
7349                                                        uint32_t level,
7350                                                        union spoolss_DriverInfo **info_p,
7351                                                        uint32_t *count_p)
7352 {
7353         int i;
7354         uint32_t version;
7355         struct spoolss_DriverInfo8 *driver;
7356         union spoolss_DriverInfo *info = NULL;
7357         uint32_t count = 0;
7358         WERROR result = WERR_OK;
7359         uint32_t num_drivers;
7360         const char **drivers;
7361         struct dcerpc_binding_handle *b;
7362         TALLOC_CTX *tmp_ctx = NULL;
7363
7364         *count_p = 0;
7365         *info_p = NULL;
7366
7367         tmp_ctx = talloc_new(mem_ctx);
7368         if (!tmp_ctx) {
7369                 return WERR_NOMEM;
7370         }
7371
7372         result = winreg_printer_binding_handle(tmp_ctx,
7373                                                session_info,
7374                                                msg_ctx,
7375                                                &b);
7376         if (!W_ERROR_IS_OK(result)) {
7377                 goto out;
7378         }
7379
7380         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7381                 result = winreg_get_driver_list(tmp_ctx, b,
7382                                                 architecture, version,
7383                                                 &num_drivers, &drivers);
7384                 if (!W_ERROR_IS_OK(result)) {
7385                         goto out;
7386                 }
7387                 DEBUG(4, ("we have:[%d] drivers in environment"
7388                           " [%s] and version [%d]\n",
7389                           num_drivers, architecture, version));
7390
7391                 if (num_drivers != 0) {
7392                         info = talloc_realloc(tmp_ctx, info,
7393                                                     union spoolss_DriverInfo,
7394                                                     count + num_drivers);
7395                         if (!info) {
7396                                 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7397                                         "failed to enlarge driver info buffer!\n"));
7398                                 result = WERR_NOMEM;
7399                                 goto out;
7400                         }
7401                 }
7402
7403                 for (i = 0; i < num_drivers; i++) {
7404                         DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7405
7406                         result = winreg_get_driver(tmp_ctx, b,
7407                                                    architecture, drivers[i],
7408                                                    version, &driver);
7409                         if (!W_ERROR_IS_OK(result)) {
7410                                 goto out;
7411                         }
7412
7413                         switch (level) {
7414                         case 1:
7415                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
7416                                                                    driver, servername);
7417                                 break;
7418                         case 2:
7419                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
7420                                                                    driver, servername);
7421                                 break;
7422                         case 3:
7423                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
7424                                                                    driver, servername);
7425                                 break;
7426                         case 4:
7427                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
7428                                                                    driver, servername);
7429                                 break;
7430                         case 5:
7431                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
7432                                                                    driver, servername);
7433                                 break;
7434                         case 6:
7435                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
7436                                                                    driver, servername);
7437                                 break;
7438                         case 8:
7439                                 result = fill_printer_driver_info8(info, &info[count+i].info8,
7440                                                                    driver, servername);
7441                                 break;
7442                         default:
7443                                 result = WERR_UNKNOWN_LEVEL;
7444                                 break;
7445                         }
7446
7447                         TALLOC_FREE(driver);
7448
7449                         if (!W_ERROR_IS_OK(result)) {
7450                                 goto out;
7451                         }
7452                 }
7453
7454                 count += num_drivers;
7455                 TALLOC_FREE(drivers);
7456         }
7457
7458 out:
7459         if (W_ERROR_IS_OK(result)) {
7460                 *info_p = talloc_move(mem_ctx, &info);
7461                 *count_p = count;
7462         }
7463
7464         talloc_free(tmp_ctx);
7465         return result;
7466 }
7467
7468 /****************************************************************************
7469  Enumerates all printer drivers by level.
7470 ****************************************************************************/
7471
7472 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7473                                        const struct auth_session_info *session_info,
7474                                        struct messaging_context *msg_ctx,
7475                                        const char *servername,
7476                                        const char *architecture,
7477                                        uint32_t level,
7478                                        union spoolss_DriverInfo **info_p,
7479                                        uint32_t *count_p)
7480 {
7481         uint32_t a,i;
7482         WERROR result = WERR_OK;
7483
7484         if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7485
7486                 for (a=0; archi_table[a].long_archi != NULL; a++) {
7487
7488                         union spoolss_DriverInfo *info = NULL;
7489                         uint32_t count = 0;
7490
7491                         result = enumprinterdrivers_level_by_architecture(mem_ctx,
7492                                                                           session_info,
7493                                                                           msg_ctx,
7494                                                                           servername,
7495                                                                           archi_table[a].long_archi,
7496                                                                           level,
7497                                                                           &info,
7498                                                                           &count);
7499                         if (!W_ERROR_IS_OK(result)) {
7500                                 continue;
7501                         }
7502
7503                         for (i=0; i < count; i++) {
7504                                 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7505                                              info[i], info_p, count_p);
7506                         }
7507                 }
7508
7509                 return result;
7510         }
7511
7512         return enumprinterdrivers_level_by_architecture(mem_ctx,
7513                                                         session_info,
7514                                                         msg_ctx,
7515                                                         servername,
7516                                                         architecture,
7517                                                         level,
7518                                                         info_p,
7519                                                         count_p);
7520 }
7521
7522 /****************************************************************
7523  _spoolss_EnumPrinterDrivers
7524 ****************************************************************/
7525
7526 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7527                                    struct spoolss_EnumPrinterDrivers *r)
7528 {
7529         const char *cservername;
7530         WERROR result;
7531
7532         /* that's an [in out] buffer */
7533
7534         if (!r->in.buffer && (r->in.offered != 0)) {
7535                 return WERR_INVALID_PARAM;
7536         }
7537
7538         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7539
7540         *r->out.needed = 0;
7541         *r->out.count = 0;
7542         *r->out.info = NULL;
7543
7544         cservername = canon_servername(r->in.server);
7545
7546         if (!is_myname_or_ipaddr(cservername)) {
7547                 return WERR_UNKNOWN_PRINTER_DRIVER;
7548         }
7549
7550         result = enumprinterdrivers_level(p->mem_ctx,
7551                                           get_session_info_system(),
7552                                           p->msg_ctx,
7553                                           cservername,
7554                                           r->in.environment,
7555                                           r->in.level,
7556                                           r->out.info,
7557                                           r->out.count);
7558         if (!W_ERROR_IS_OK(result)) {
7559                 return result;
7560         }
7561
7562         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7563                                                      spoolss_EnumPrinterDrivers,
7564                                                      *r->out.info, r->in.level,
7565                                                      *r->out.count);
7566         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7567         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7568
7569         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7570 }
7571
7572 /****************************************************************
7573  _spoolss_EnumForms
7574 ****************************************************************/
7575
7576 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7577                           struct spoolss_EnumForms *r)
7578 {
7579         WERROR result;
7580
7581         *r->out.count = 0;
7582         *r->out.needed = 0;
7583         *r->out.info = NULL;
7584
7585         /* that's an [in out] buffer */
7586
7587         if (!r->in.buffer && (r->in.offered != 0) ) {
7588                 return WERR_INVALID_PARAM;
7589         }
7590
7591         DEBUG(4,("_spoolss_EnumForms\n"));
7592         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7593         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7594
7595         switch (r->in.level) {
7596         case 1:
7597                 result = winreg_printer_enumforms1_internal(p->mem_ctx,
7598                                                    get_session_info_system(),
7599                                                    p->msg_ctx,
7600                                                    r->out.count,
7601                                                    r->out.info);
7602                 break;
7603         default:
7604                 result = WERR_UNKNOWN_LEVEL;
7605                 break;
7606         }
7607
7608         if (!W_ERROR_IS_OK(result)) {
7609                 return result;
7610         }
7611
7612         if (*r->out.count == 0) {
7613                 return WERR_NO_MORE_ITEMS;
7614         }
7615
7616         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7617                                                      spoolss_EnumForms,
7618                                                      *r->out.info, r->in.level,
7619                                                      *r->out.count);
7620         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7621         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7622
7623         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7624 }
7625
7626 /****************************************************************
7627  _spoolss_GetForm
7628 ****************************************************************/
7629
7630 WERROR _spoolss_GetForm(struct pipes_struct *p,
7631                         struct spoolss_GetForm *r)
7632 {
7633         WERROR result;
7634
7635         /* that's an [in out] buffer */
7636
7637         if (!r->in.buffer && (r->in.offered != 0)) {
7638                 return WERR_INVALID_PARAM;
7639         }
7640
7641         DEBUG(4,("_spoolss_GetForm\n"));
7642         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7643         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7644
7645         switch (r->in.level) {
7646         case 1:
7647                 result = winreg_printer_getform1_internal(p->mem_ctx,
7648                                                  get_session_info_system(),
7649                                                  p->msg_ctx,
7650                                                  r->in.form_name,
7651                                                  &r->out.info->info1);
7652                 break;
7653         default:
7654                 result = WERR_UNKNOWN_LEVEL;
7655                 break;
7656         }
7657
7658         if (!W_ERROR_IS_OK(result)) {
7659                 TALLOC_FREE(r->out.info);
7660                 return result;
7661         }
7662
7663         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
7664                                                r->out.info, r->in.level);
7665         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7666
7667         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7668 }
7669
7670 /****************************************************************************
7671 ****************************************************************************/
7672
7673 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7674                           struct spoolss_PortInfo1 *r,
7675                           const char *name)
7676 {
7677         r->port_name = talloc_strdup(mem_ctx, name);
7678         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7679
7680         return WERR_OK;
7681 }
7682
7683 /****************************************************************************
7684  TODO: This probably needs distinguish between TCP/IP and Local ports
7685  somehow.
7686 ****************************************************************************/
7687
7688 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7689                           struct spoolss_PortInfo2 *r,
7690                           const char *name)
7691 {
7692         r->port_name = talloc_strdup(mem_ctx, name);
7693         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7694
7695         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7696         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7697
7698         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7699         W_ERROR_HAVE_NO_MEMORY(r->description);
7700
7701         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7702         r->reserved = 0;
7703
7704         return WERR_OK;
7705 }
7706
7707
7708 /****************************************************************************
7709  wrapper around the enumer ports command
7710 ****************************************************************************/
7711
7712 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7713 {
7714         char *cmd = lp_enumports_cmd();
7715         char **qlines = NULL;
7716         char *command = NULL;
7717         int numlines;
7718         int ret;
7719         int fd;
7720
7721         *count = 0;
7722         *lines = NULL;
7723
7724         /* if no hook then just fill in the default port */
7725
7726         if ( !*cmd ) {
7727                 if (!(qlines = talloc_array( NULL, char*, 2 ))) {
7728                         return WERR_NOMEM;
7729                 }
7730                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7731                         TALLOC_FREE(qlines);
7732                         return WERR_NOMEM;
7733                 }
7734                 qlines[1] = NULL;
7735                 numlines = 1;
7736         }
7737         else {
7738                 /* we have a valid enumport command */
7739
7740                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7741                 if (!command) {
7742                         return WERR_NOMEM;
7743                 }
7744
7745                 DEBUG(10,("Running [%s]\n", command));
7746                 ret = smbrun(command, &fd);
7747                 DEBUG(10,("Returned [%d]\n", ret));
7748                 TALLOC_FREE(command);
7749                 if (ret != 0) {
7750                         if (fd != -1) {
7751                                 close(fd);
7752                         }
7753                         return WERR_ACCESS_DENIED;
7754                 }
7755
7756                 numlines = 0;
7757                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7758                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7759                 close(fd);
7760         }
7761
7762         *count = numlines;
7763         *lines = qlines;
7764
7765         return WERR_OK;
7766 }
7767
7768 /****************************************************************************
7769  enumports level 1.
7770 ****************************************************************************/
7771
7772 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7773                                 union spoolss_PortInfo **info_p,
7774                                 uint32_t *count)
7775 {
7776         union spoolss_PortInfo *info = NULL;
7777         int i=0;
7778         WERROR result = WERR_OK;
7779         char **qlines = NULL;
7780         int numlines = 0;
7781
7782         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7783         if (!W_ERROR_IS_OK(result)) {
7784                 goto out;
7785         }
7786
7787         if (numlines) {
7788                 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
7789                 if (!info) {
7790                         DEBUG(10,("Returning WERR_NOMEM\n"));
7791                         result = WERR_NOMEM;
7792                         goto out;
7793                 }
7794
7795                 for (i=0; i<numlines; i++) {
7796                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7797                         result = fill_port_1(info, &info[i].info1, qlines[i]);
7798                         if (!W_ERROR_IS_OK(result)) {
7799                                 goto out;
7800                         }
7801                 }
7802         }
7803         TALLOC_FREE(qlines);
7804
7805 out:
7806         if (!W_ERROR_IS_OK(result)) {
7807                 TALLOC_FREE(info);
7808                 TALLOC_FREE(qlines);
7809                 *count = 0;
7810                 *info_p = NULL;
7811                 return result;
7812         }
7813
7814         *info_p = info;
7815         *count = numlines;
7816
7817         return WERR_OK;
7818 }
7819
7820 /****************************************************************************
7821  enumports level 2.
7822 ****************************************************************************/
7823
7824 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7825                                 union spoolss_PortInfo **info_p,
7826                                 uint32_t *count)
7827 {
7828         union spoolss_PortInfo *info = NULL;
7829         int i=0;
7830         WERROR result = WERR_OK;
7831         char **qlines = NULL;
7832         int numlines = 0;
7833
7834         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7835         if (!W_ERROR_IS_OK(result)) {
7836                 goto out;
7837         }
7838
7839         if (numlines) {
7840                 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
7841                 if (!info) {
7842                         DEBUG(10,("Returning WERR_NOMEM\n"));
7843                         result = WERR_NOMEM;
7844                         goto out;
7845                 }
7846
7847                 for (i=0; i<numlines; i++) {
7848                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7849                         result = fill_port_2(info, &info[i].info2, qlines[i]);
7850                         if (!W_ERROR_IS_OK(result)) {
7851                                 goto out;
7852                         }
7853                 }
7854         }
7855         TALLOC_FREE(qlines);
7856
7857 out:
7858         if (!W_ERROR_IS_OK(result)) {
7859                 TALLOC_FREE(info);
7860                 TALLOC_FREE(qlines);
7861                 *count = 0;
7862                 *info_p = NULL;
7863                 return result;
7864         }
7865
7866         *info_p = info;
7867         *count = numlines;
7868
7869         return WERR_OK;
7870 }
7871
7872 /****************************************************************
7873  _spoolss_EnumPorts
7874 ****************************************************************/
7875
7876 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
7877                           struct spoolss_EnumPorts *r)
7878 {
7879         WERROR result;
7880
7881         /* that's an [in out] buffer */
7882
7883         if (!r->in.buffer && (r->in.offered != 0)) {
7884                 return WERR_INVALID_PARAM;
7885         }
7886
7887         DEBUG(4,("_spoolss_EnumPorts\n"));
7888
7889         *r->out.count = 0;
7890         *r->out.needed = 0;
7891         *r->out.info = NULL;
7892
7893         switch (r->in.level) {
7894         case 1:
7895                 result = enumports_level_1(p->mem_ctx, r->out.info,
7896                                            r->out.count);
7897                 break;
7898         case 2:
7899                 result = enumports_level_2(p->mem_ctx, r->out.info,
7900                                            r->out.count);
7901                 break;
7902         default:
7903                 return WERR_UNKNOWN_LEVEL;
7904         }
7905
7906         if (!W_ERROR_IS_OK(result)) {
7907                 return result;
7908         }
7909
7910         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7911                                                      spoolss_EnumPorts,
7912                                                      *r->out.info, r->in.level,
7913                                                      *r->out.count);
7914         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7915         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7916
7917         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7918 }
7919
7920 /****************************************************************************
7921 ****************************************************************************/
7922
7923 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
7924                                            const char *server,
7925                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
7926                                            struct spoolss_DeviceMode *devmode,
7927                                            struct security_descriptor *secdesc,
7928                                            struct spoolss_UserLevelCtr *user_ctr,
7929                                            struct policy_handle *handle)
7930 {
7931         struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
7932         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
7933         int     snum;
7934         WERROR err = WERR_OK;
7935
7936         /* samba does not have a concept of local, non-shared printers yet, so
7937          * make sure we always setup sharename - gd */
7938         if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
7939             (info2->printername != NULL && info2->printername[0] != '\0')) {
7940                 DEBUG(5, ("spoolss_addprinterex_level_2: "
7941                         "no sharename has been set, setting printername %s as sharename\n",
7942                         info2->printername));
7943                 info2->sharename = info2->printername;
7944         }
7945
7946         /* check to see if the printer already exists */
7947         if ((snum = print_queue_snum(info2->sharename)) != -1) {
7948                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7949                         info2->sharename));
7950                 return WERR_PRINTER_ALREADY_EXISTS;
7951         }
7952
7953         if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7954                 if ((snum = print_queue_snum(info2->printername)) != -1) {
7955                         DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7956                                 info2->printername));
7957                         return WERR_PRINTER_ALREADY_EXISTS;
7958                 }
7959         }
7960
7961         /* validate printer info struct */
7962         if (!info2->printername || strlen(info2->printername) == 0) {
7963                 return WERR_INVALID_PRINTER_NAME;
7964         }
7965         if (!info2->portname || strlen(info2->portname) == 0) {
7966                 return WERR_UNKNOWN_PORT;
7967         }
7968         if (!info2->drivername || strlen(info2->drivername) == 0) {
7969                 return WERR_UNKNOWN_PRINTER_DRIVER;
7970         }
7971         if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
7972                 return WERR_UNKNOWN_PRINTPROCESSOR;
7973         }
7974
7975         /* FIXME!!!  smbd should check to see if the driver is installed before
7976            trying to add a printer like this  --jerry */
7977
7978         if (*lp_addprinter_cmd() ) {
7979                 char *raddr;
7980
7981                 raddr = tsocket_address_inet_addr_string(p->remote_address,
7982                                                          p->mem_ctx);
7983                 if (raddr == NULL) {
7984                         return WERR_NOMEM;
7985                 }
7986
7987                 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
7988                                        info2, raddr,
7989                                        p->msg_ctx) ) {
7990                         return WERR_ACCESS_DENIED;
7991                 }
7992         } else {
7993                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
7994                         "smb.conf parameter \"addprinter command\" is defined. This "
7995                         "parameter must exist for this call to succeed\n",
7996                         info2->sharename ));
7997         }
7998
7999         if ((snum = print_queue_snum(info2->sharename)) == -1) {
8000                 return WERR_ACCESS_DENIED;
8001         }
8002
8003         /* you must be a printer admin to add a new printer */
8004         if (!print_access_check(p->session_info,
8005                                 p->msg_ctx,
8006                                 snum,
8007                                 PRINTER_ACCESS_ADMINISTER)) {
8008                 return WERR_ACCESS_DENIED;
8009         }
8010
8011         /*
8012          * Do sanity check on the requested changes for Samba.
8013          */
8014
8015         if (!check_printer_ok(p->mem_ctx, info2, snum)) {
8016                 return WERR_INVALID_PARAM;
8017         }
8018
8019         if (devmode == NULL) {
8020                 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
8021         }
8022
8023         update_dsspooler(p->mem_ctx,
8024                          get_session_info_system(),
8025                          p->msg_ctx,
8026                          0,
8027                          info2,
8028                          NULL);
8029
8030         err = winreg_update_printer_internal(p->mem_ctx,
8031                                     get_session_info_system(),
8032                                     p->msg_ctx,
8033                                     info2->sharename,
8034                                     info2_mask,
8035                                     info2,
8036                                     devmode,
8037                                     secdesc);
8038         if (!W_ERROR_IS_OK(err)) {
8039                 return err;
8040         }
8041
8042         err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
8043         if (!W_ERROR_IS_OK(err)) {
8044                 /* Handle open failed - remove addition. */
8045                 ZERO_STRUCTP(handle);
8046                 return err;
8047         }
8048
8049         return WERR_OK;
8050 }
8051
8052 /****************************************************************
8053  _spoolss_AddPrinterEx
8054 ****************************************************************/
8055
8056 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
8057                              struct spoolss_AddPrinterEx *r)
8058 {
8059         switch (r->in.info_ctr->level) {
8060         case 1:
8061                 /* we don't handle yet */
8062                 /* but I know what to do ... */
8063                 return WERR_UNKNOWN_LEVEL;
8064         case 2:
8065                 return spoolss_addprinterex_level_2(p, r->in.server,
8066                                                     r->in.info_ctr,
8067                                                     r->in.devmode_ctr->devmode,
8068                                                     r->in.secdesc_ctr->sd,
8069                                                     r->in.userlevel_ctr,
8070                                                     r->out.handle);
8071         default:
8072                 return WERR_UNKNOWN_LEVEL;
8073         }
8074 }
8075
8076 /****************************************************************
8077  _spoolss_AddPrinter
8078 ****************************************************************/
8079
8080 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
8081                            struct spoolss_AddPrinter *r)
8082 {
8083         struct spoolss_AddPrinterEx a;
8084         struct spoolss_UserLevelCtr userlevel_ctr;
8085
8086         ZERO_STRUCT(userlevel_ctr);
8087
8088         userlevel_ctr.level = 1;
8089
8090         a.in.server             = r->in.server;
8091         a.in.info_ctr           = r->in.info_ctr;
8092         a.in.devmode_ctr        = r->in.devmode_ctr;
8093         a.in.secdesc_ctr        = r->in.secdesc_ctr;
8094         a.in.userlevel_ctr      = &userlevel_ctr;
8095         a.out.handle            = r->out.handle;
8096
8097         return _spoolss_AddPrinterEx(p, &a);
8098 }
8099
8100 /****************************************************************
8101  _spoolss_AddPrinterDriverEx
8102 ****************************************************************/
8103
8104 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
8105                                    struct spoolss_AddPrinterDriverEx *r)
8106 {
8107         WERROR err = WERR_OK;
8108         const char *driver_name = NULL;
8109         uint32_t version;
8110         const char *fn;
8111
8112         switch (p->opnum) {
8113                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
8114                         fn = "_spoolss_AddPrinterDriver";
8115                         break;
8116                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
8117                         fn = "_spoolss_AddPrinterDriverEx";
8118                         break;
8119                 default:
8120                         return WERR_INVALID_PARAM;
8121         }
8122
8123         /*
8124          * we only support the semantics of AddPrinterDriver()
8125          * i.e. only copy files that are newer than existing ones
8126          */
8127
8128         if (r->in.flags == 0) {
8129                 return WERR_INVALID_PARAM;
8130         }
8131
8132         if (r->in.flags != APD_COPY_NEW_FILES) {
8133                 return WERR_ACCESS_DENIED;
8134         }
8135
8136         /* FIXME */
8137         if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
8138                 /* Clever hack from Martin Zielinski <mz@seh.de>
8139                  * to allow downgrade from level 8 (Vista).
8140                  */
8141                 DEBUG(0,("%s: level %d not yet implemented\n", fn,
8142                         r->in.info_ctr->level));
8143                 return WERR_UNKNOWN_LEVEL;
8144         }
8145
8146         DEBUG(5,("Cleaning driver's information\n"));
8147         err = clean_up_driver_struct(p->mem_ctx, p->session_info, r->in.info_ctr);
8148         if (!W_ERROR_IS_OK(err))
8149                 goto done;
8150
8151         DEBUG(5,("Moving driver to final destination\n"));
8152         err = move_driver_to_download_area(p->session_info, r->in.info_ctr);
8153         if (!W_ERROR_IS_OK(err)) {
8154                 goto done;
8155         }
8156
8157         err = winreg_add_driver_internal(p->mem_ctx,
8158                                 get_session_info_system(),
8159                                 p->msg_ctx,
8160                                 r->in.info_ctr,
8161                                 &driver_name,
8162                                 &version);
8163         if (!W_ERROR_IS_OK(err)) {
8164                 goto done;
8165         }
8166
8167         /*
8168          * I think this is where he DrvUpgradePrinter() hook would be
8169          * be called in a driver's interface DLL on a Windows NT 4.0/2k
8170          * server.  Right now, we just need to send ourselves a message
8171          * to update each printer bound to this driver.   --jerry
8172          */
8173
8174         if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8175                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8176                         fn, driver_name));
8177         }
8178
8179 done:
8180         return err;
8181 }
8182
8183 /****************************************************************
8184  _spoolss_AddPrinterDriver
8185 ****************************************************************/
8186
8187 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8188                                  struct spoolss_AddPrinterDriver *r)
8189 {
8190         struct spoolss_AddPrinterDriverEx a;
8191
8192         switch (r->in.info_ctr->level) {
8193         case 2:
8194         case 3:
8195         case 4:
8196         case 5:
8197                 break;
8198         default:
8199                 return WERR_UNKNOWN_LEVEL;
8200         }
8201
8202         a.in.servername         = r->in.servername;
8203         a.in.info_ctr           = r->in.info_ctr;
8204         a.in.flags              = APD_COPY_NEW_FILES;
8205
8206         return _spoolss_AddPrinterDriverEx(p, &a);
8207 }
8208
8209 /****************************************************************************
8210 ****************************************************************************/
8211
8212 struct _spoolss_paths {
8213         int type;
8214         const char *share;
8215         const char *dir;
8216 };
8217
8218 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8219
8220 static const struct _spoolss_paths spoolss_paths[]= {
8221         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
8222         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
8223 };
8224
8225 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8226                                           const char *servername,
8227                                           const char *environment,
8228                                           int component,
8229                                           char **path)
8230 {
8231         const char *pservername = NULL;
8232         const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
8233         const char *short_archi;
8234
8235         *path = NULL;
8236
8237         /* environment may be empty */
8238         if (environment && strlen(environment)) {
8239                 long_archi = environment;
8240         }
8241
8242         /* servername may be empty */
8243         if (servername && strlen(servername)) {
8244                 pservername = canon_servername(servername);
8245
8246                 if (!is_myname_or_ipaddr(pservername)) {
8247                         return WERR_INVALID_PARAM;
8248                 }
8249         }
8250
8251         if (!(short_archi = get_short_archi(long_archi))) {
8252                 return WERR_INVALID_ENVIRONMENT;
8253         }
8254
8255         switch (component) {
8256         case SPOOLSS_PRTPROCS_PATH:
8257         case SPOOLSS_DRIVER_PATH:
8258                 if (pservername) {
8259                         *path = talloc_asprintf(mem_ctx,
8260                                         "\\\\%s\\%s\\%s",
8261                                         pservername,
8262                                         spoolss_paths[component].share,
8263                                         short_archi);
8264                 } else {
8265                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8266                                         SPOOLSS_DEFAULT_SERVER_PATH,
8267                                         spoolss_paths[component].dir,
8268                                         short_archi);
8269                 }
8270                 break;
8271         default:
8272                 return WERR_INVALID_PARAM;
8273         }
8274
8275         if (!*path) {
8276                 return WERR_NOMEM;
8277         }
8278
8279         return WERR_OK;
8280 }
8281
8282 /****************************************************************************
8283 ****************************************************************************/
8284
8285 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8286                                           const char *servername,
8287                                           const char *environment,
8288                                           struct spoolss_DriverDirectoryInfo1 *r)
8289 {
8290         WERROR werr;
8291         char *path = NULL;
8292
8293         werr = compose_spoolss_server_path(mem_ctx,
8294                                            servername,
8295                                            environment,
8296                                            SPOOLSS_DRIVER_PATH,
8297                                            &path);
8298         if (!W_ERROR_IS_OK(werr)) {
8299                 return werr;
8300         }
8301
8302         DEBUG(4,("printer driver directory: [%s]\n", path));
8303
8304         r->directory_name = path;
8305
8306         return WERR_OK;
8307 }
8308
8309 /****************************************************************
8310  _spoolss_GetPrinterDriverDirectory
8311 ****************************************************************/
8312
8313 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8314                                           struct spoolss_GetPrinterDriverDirectory *r)
8315 {
8316         WERROR werror;
8317
8318         /* that's an [in out] buffer */
8319
8320         if (!r->in.buffer && (r->in.offered != 0)) {
8321                 return WERR_INVALID_PARAM;
8322         }
8323
8324         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8325                 r->in.level));
8326
8327         *r->out.needed = 0;
8328
8329         /* r->in.level is ignored */
8330
8331         werror = getprinterdriverdir_level_1(p->mem_ctx,
8332                                              r->in.server,
8333                                              r->in.environment,
8334                                              &r->out.info->info1);
8335         if (!W_ERROR_IS_OK(werror)) {
8336                 TALLOC_FREE(r->out.info);
8337                 return werror;
8338         }
8339
8340         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8341                                                r->out.info, r->in.level);
8342         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8343
8344         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8345 }
8346
8347 /****************************************************************
8348  _spoolss_EnumPrinterData
8349 ****************************************************************/
8350
8351 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8352                                 struct spoolss_EnumPrinterData *r)
8353 {
8354         WERROR result;
8355         struct spoolss_EnumPrinterDataEx r2;
8356         uint32_t count;
8357         struct spoolss_PrinterEnumValues *info, *val = NULL;
8358         uint32_t needed;
8359
8360         r2.in.handle    = r->in.handle;
8361         r2.in.key_name  = "PrinterDriverData";
8362         r2.in.offered   = 0;
8363         r2.out.count    = &count;
8364         r2.out.info     = &info;
8365         r2.out.needed   = &needed;
8366
8367         result = _spoolss_EnumPrinterDataEx(p, &r2);
8368         if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8369                 r2.in.offered = needed;
8370                 result = _spoolss_EnumPrinterDataEx(p, &r2);
8371         }
8372         if (!W_ERROR_IS_OK(result)) {
8373                 return result;
8374         }
8375
8376         /*
8377          * The NT machine wants to know the biggest size of value and data
8378          *
8379          * cf: MSDN EnumPrinterData remark section
8380          */
8381
8382         if (!r->in.value_offered && !r->in.data_offered) {
8383                 uint32_t biggest_valuesize = 0;
8384                 uint32_t biggest_datasize = 0;
8385                 int i, name_length;
8386
8387                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8388
8389                 for (i=0; i<count; i++) {
8390
8391                         name_length = strlen(info[i].value_name);
8392                         if (strlen(info[i].value_name) > biggest_valuesize) {
8393                                 biggest_valuesize = name_length;
8394                         }
8395
8396                         if (info[i].data_length > biggest_datasize) {
8397                                 biggest_datasize = info[i].data_length;
8398                         }
8399
8400                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8401                                 biggest_datasize));
8402                 }
8403
8404                 /* the value is an UNICODE string but real_value_size is the length
8405                    in bytes including the trailing 0 */
8406
8407                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8408                 *r->out.data_needed  = biggest_datasize;
8409
8410                 DEBUG(6,("final values: [%d], [%d]\n",
8411                         *r->out.value_needed, *r->out.data_needed));
8412
8413                 return WERR_OK;
8414         }
8415
8416         if (r->in.enum_index < count) {
8417                 val = &info[r->in.enum_index];
8418         }
8419
8420         if (val == NULL) {
8421                 /* out_value should default to "" or else NT4 has
8422                    problems unmarshalling the response */
8423
8424                 if (r->in.value_offered) {
8425                         *r->out.value_needed = 1;
8426                         r->out.value_name = talloc_strdup(r, "");
8427                         if (!r->out.value_name) {
8428                                 return WERR_NOMEM;
8429                         }
8430                 } else {
8431                         r->out.value_name = NULL;
8432                         *r->out.value_needed = 0;
8433                 }
8434
8435                 /* the data is counted in bytes */
8436
8437                 *r->out.data_needed = r->in.data_offered;
8438
8439                 result = WERR_NO_MORE_ITEMS;
8440         } else {
8441                 /*
8442                  * the value is:
8443                  * - counted in bytes in the request
8444                  * - counted in UNICODE chars in the max reply
8445                  * - counted in bytes in the real size
8446                  *
8447                  * take a pause *before* coding not *during* coding
8448                  */
8449
8450                 /* name */
8451                 if (r->in.value_offered) {
8452                         r->out.value_name = talloc_strdup(r, val->value_name);
8453                         if (!r->out.value_name) {
8454                                 return WERR_NOMEM;
8455                         }
8456                         *r->out.value_needed = val->value_name_len;
8457                 } else {
8458                         r->out.value_name = NULL;
8459                         *r->out.value_needed = 0;
8460                 }
8461
8462                 /* type */
8463
8464                 *r->out.type = val->type;
8465
8466                 /* data - counted in bytes */
8467
8468                 /*
8469                  * See the section "Dynamically Typed Query Parameters"
8470                  * in MS-RPRN.
8471                  */
8472
8473                 if (r->out.data && val->data && val->data->data &&
8474                                 val->data_length && r->in.data_offered) {
8475                         memcpy(r->out.data, val->data->data,
8476                                 MIN(val->data_length,r->in.data_offered));
8477                 }
8478
8479                 *r->out.data_needed = val->data_length;
8480
8481                 result = WERR_OK;
8482         }
8483
8484         return result;
8485 }
8486
8487 /****************************************************************
8488  _spoolss_SetPrinterData
8489 ****************************************************************/
8490
8491 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8492                                struct spoolss_SetPrinterData *r)
8493 {
8494         struct spoolss_SetPrinterDataEx r2;
8495
8496         r2.in.handle            = r->in.handle;
8497         r2.in.key_name          = "PrinterDriverData";
8498         r2.in.value_name        = r->in.value_name;
8499         r2.in.type              = r->in.type;
8500         r2.in.data              = r->in.data;
8501         r2.in.offered           = r->in.offered;
8502
8503         return _spoolss_SetPrinterDataEx(p, &r2);
8504 }
8505
8506 /****************************************************************
8507  _spoolss_ResetPrinter
8508 ****************************************************************/
8509
8510 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8511                              struct spoolss_ResetPrinter *r)
8512 {
8513         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8514         int             snum;
8515
8516         DEBUG(5,("_spoolss_ResetPrinter\n"));
8517
8518         /*
8519          * All we do is to check to see if the handle and queue is valid.
8520          * This call really doesn't mean anything to us because we only
8521          * support RAW printing.   --jerry
8522          */
8523
8524         if (!Printer) {
8525                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8526                         OUR_HANDLE(r->in.handle)));
8527                 return WERR_BADFID;
8528         }
8529
8530         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8531                 return WERR_BADFID;
8532
8533
8534         /* blindly return success */
8535         return WERR_OK;
8536 }
8537
8538 /****************************************************************
8539  _spoolss_DeletePrinterData
8540 ****************************************************************/
8541
8542 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8543                                   struct spoolss_DeletePrinterData *r)
8544 {
8545         struct spoolss_DeletePrinterDataEx r2;
8546
8547         r2.in.handle            = r->in.handle;
8548         r2.in.key_name          = "PrinterDriverData";
8549         r2.in.value_name        = r->in.value_name;
8550
8551         return _spoolss_DeletePrinterDataEx(p, &r2);
8552 }
8553
8554 /****************************************************************
8555  _spoolss_AddForm
8556 ****************************************************************/
8557
8558 WERROR _spoolss_AddForm(struct pipes_struct *p,
8559                         struct spoolss_AddForm *r)
8560 {
8561         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8562         int snum = -1;
8563         WERROR status = WERR_OK;
8564         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8565         struct dcerpc_binding_handle *b;
8566         TALLOC_CTX *tmp_ctx = NULL;
8567
8568         DEBUG(5,("_spoolss_AddForm\n"));
8569
8570         if (!Printer) {
8571                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8572                         OUR_HANDLE(r->in.handle)));
8573                 return WERR_BADFID;
8574         }
8575
8576         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8577            and not a printer admin, then fail */
8578
8579         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8580             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8581             !token_contains_name_in_list(uidtoname(p->session_info->unix_token->uid),
8582                                           p->session_info->info->domain_name,
8583                                           NULL,
8584                                           p->session_info->security_token,
8585                                           lp_printer_admin(snum))) {
8586                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8587                 return WERR_ACCESS_DENIED;
8588         }
8589
8590         switch (form->flags) {
8591         case SPOOLSS_FORM_USER:
8592         case SPOOLSS_FORM_BUILTIN:
8593         case SPOOLSS_FORM_PRINTER:
8594                 break;
8595         default:
8596                 return WERR_INVALID_PARAM;
8597         }
8598
8599         tmp_ctx = talloc_new(p->mem_ctx);
8600         if (!tmp_ctx) {
8601                 return WERR_NOMEM;
8602         }
8603
8604         status = winreg_printer_binding_handle(tmp_ctx,
8605                                                get_session_info_system(),
8606                                                p->msg_ctx,
8607                                                &b);
8608         if (!W_ERROR_IS_OK(status)) {
8609                 goto done;
8610         }
8611
8612         status = winreg_printer_addform1(tmp_ctx, b, form);
8613         if (!W_ERROR_IS_OK(status)) {
8614                 goto done;
8615         }
8616
8617         /*
8618          * ChangeID must always be set if this is a printer
8619          */
8620         if (Printer->printer_type == SPLHND_PRINTER) {
8621                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8622                         status = WERR_BADFID;
8623                         goto done;
8624                 }
8625
8626                 status = winreg_printer_update_changeid(tmp_ctx, b,
8627                                                         lp_const_servicename(snum));
8628         }
8629
8630 done:
8631         talloc_free(tmp_ctx);
8632         return status;
8633 }
8634
8635 /****************************************************************
8636  _spoolss_DeleteForm
8637 ****************************************************************/
8638
8639 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8640                            struct spoolss_DeleteForm *r)
8641 {
8642         const char *form_name = r->in.form_name;
8643         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8644         int snum = -1;
8645         WERROR status = WERR_OK;
8646         struct dcerpc_binding_handle *b;
8647         TALLOC_CTX *tmp_ctx = NULL;
8648
8649         DEBUG(5,("_spoolss_DeleteForm\n"));
8650
8651         if (!Printer) {
8652                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8653                         OUR_HANDLE(r->in.handle)));
8654                 return WERR_BADFID;
8655         }
8656
8657         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8658             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8659             !token_contains_name_in_list(uidtoname(p->session_info->unix_token->uid),
8660                                           p->session_info->info->domain_name,
8661                                           NULL,
8662                                           p->session_info->security_token,
8663                                           lp_printer_admin(snum))) {
8664                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8665                 return WERR_ACCESS_DENIED;
8666         }
8667
8668         tmp_ctx = talloc_new(p->mem_ctx);
8669         if (!tmp_ctx) {
8670                 return WERR_NOMEM;
8671         }
8672
8673         status = winreg_printer_binding_handle(tmp_ctx,
8674                                                get_session_info_system(),
8675                                                p->msg_ctx,
8676                                                &b);
8677         if (!W_ERROR_IS_OK(status)) {
8678                 goto done;
8679         }
8680
8681         status = winreg_printer_deleteform1(tmp_ctx, b, form_name);
8682         if (!W_ERROR_IS_OK(status)) {
8683                 goto done;
8684         }
8685
8686         /*
8687          * ChangeID must always be set if this is a printer
8688          */
8689         if (Printer->printer_type == SPLHND_PRINTER) {
8690                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8691                         status = WERR_BADFID;
8692                         goto done;
8693                 }
8694
8695                 status = winreg_printer_update_changeid(tmp_ctx, b,
8696                                                         lp_const_servicename(snum));
8697         }
8698
8699 done:
8700         talloc_free(tmp_ctx);
8701         return status;
8702 }
8703
8704 /****************************************************************
8705  _spoolss_SetForm
8706 ****************************************************************/
8707
8708 WERROR _spoolss_SetForm(struct pipes_struct *p,
8709                         struct spoolss_SetForm *r)
8710 {
8711         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8712         const char *form_name = r->in.form_name;
8713         int snum = -1;
8714         WERROR status = WERR_OK;
8715         struct dcerpc_binding_handle *b;
8716         TALLOC_CTX *tmp_ctx = NULL;
8717
8718         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8719
8720         DEBUG(5,("_spoolss_SetForm\n"));
8721
8722         if (!Printer) {
8723                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8724                         OUR_HANDLE(r->in.handle)));
8725                 return WERR_BADFID;
8726         }
8727
8728         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8729            and not a printer admin, then fail */
8730
8731         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8732              !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8733              !token_contains_name_in_list(uidtoname(p->session_info->unix_token->uid),
8734                                           p->session_info->info->domain_name,
8735                                           NULL,
8736                                           p->session_info->security_token,
8737                                           lp_printer_admin(snum))) {
8738                 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8739                 return WERR_ACCESS_DENIED;
8740         }
8741
8742         tmp_ctx = talloc_new(p->mem_ctx);
8743         if (!tmp_ctx) {
8744                 return WERR_NOMEM;
8745         }
8746
8747         status = winreg_printer_binding_handle(tmp_ctx,
8748                                                get_session_info_system(),
8749                                                p->msg_ctx,
8750                                                &b);
8751         if (!W_ERROR_IS_OK(status)) {
8752                 goto done;
8753         }
8754
8755         status = winreg_printer_setform1(tmp_ctx, b,
8756                                          form_name,
8757                                          form);
8758         if (!W_ERROR_IS_OK(status)) {
8759                 goto done;
8760         }
8761
8762         /*
8763          * ChangeID must always be set if this is a printer
8764          */
8765         if (Printer->printer_type == SPLHND_PRINTER) {
8766                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8767                         status = WERR_BADFID;
8768                         goto done;
8769                 }
8770
8771                 status = winreg_printer_update_changeid(tmp_ctx, b,
8772                                                         lp_const_servicename(snum));
8773         }
8774
8775 done:
8776         talloc_free(tmp_ctx);
8777         return status;
8778 }
8779
8780 /****************************************************************************
8781  fill_print_processor1
8782 ****************************************************************************/
8783
8784 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8785                                     struct spoolss_PrintProcessorInfo1 *r,
8786                                     const char *print_processor_name)
8787 {
8788         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8789         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8790
8791         return WERR_OK;
8792 }
8793
8794 /****************************************************************************
8795  enumprintprocessors level 1.
8796 ****************************************************************************/
8797
8798 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8799                                           union spoolss_PrintProcessorInfo **info_p,
8800                                           uint32_t *count)
8801 {
8802         union spoolss_PrintProcessorInfo *info;
8803         WERROR result;
8804
8805         info = talloc_array(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8806         W_ERROR_HAVE_NO_MEMORY(info);
8807
8808         *count = 1;
8809
8810         result = fill_print_processor1(info, &info[0].info1, "winprint");
8811         if (!W_ERROR_IS_OK(result)) {
8812                 goto out;
8813         }
8814
8815  out:
8816         if (!W_ERROR_IS_OK(result)) {
8817                 TALLOC_FREE(info);
8818                 *count = 0;
8819                 return result;
8820         }
8821
8822         *info_p = info;
8823
8824         return WERR_OK;
8825 }
8826
8827 /****************************************************************
8828  _spoolss_EnumPrintProcessors
8829 ****************************************************************/
8830
8831 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
8832                                     struct spoolss_EnumPrintProcessors *r)
8833 {
8834         WERROR result;
8835
8836         /* that's an [in out] buffer */
8837
8838         if (!r->in.buffer && (r->in.offered != 0)) {
8839                 return WERR_INVALID_PARAM;
8840         }
8841
8842         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8843
8844         /*
8845          * Enumerate the print processors ...
8846          *
8847          * Just reply with "winprint", to keep NT happy
8848          * and I can use my nice printer checker.
8849          */
8850
8851         *r->out.count = 0;
8852         *r->out.needed = 0;
8853         *r->out.info = NULL;
8854
8855         if (!get_short_archi(r->in.environment)) {
8856                 return WERR_INVALID_ENVIRONMENT;
8857         }
8858
8859         switch (r->in.level) {
8860         case 1:
8861                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8862                                                      r->out.count);
8863                 break;
8864         default:
8865                 return WERR_UNKNOWN_LEVEL;
8866         }
8867
8868         if (!W_ERROR_IS_OK(result)) {
8869                 return result;
8870         }
8871
8872         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8873                                                      spoolss_EnumPrintProcessors,
8874                                                      *r->out.info, r->in.level,
8875                                                      *r->out.count);
8876         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8877         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8878
8879         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8880 }
8881
8882 /****************************************************************************
8883  fill_printprocdatatype1
8884 ****************************************************************************/
8885
8886 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8887                                       struct spoolss_PrintProcDataTypesInfo1 *r,
8888                                       const char *name_array)
8889 {
8890         r->name_array = talloc_strdup(mem_ctx, name_array);
8891         W_ERROR_HAVE_NO_MEMORY(r->name_array);
8892
8893         return WERR_OK;
8894 }
8895
8896 /****************************************************************************
8897  enumprintprocdatatypes level 1.
8898 ****************************************************************************/
8899
8900 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8901                                              union spoolss_PrintProcDataTypesInfo **info_p,
8902                                              uint32_t *count)
8903 {
8904         WERROR result;
8905         union spoolss_PrintProcDataTypesInfo *info;
8906
8907         info = talloc_array(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8908         W_ERROR_HAVE_NO_MEMORY(info);
8909
8910         *count = 1;
8911
8912         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8913         if (!W_ERROR_IS_OK(result)) {
8914                 goto out;
8915         }
8916
8917  out:
8918         if (!W_ERROR_IS_OK(result)) {
8919                 TALLOC_FREE(info);
8920                 *count = 0;
8921                 return result;
8922         }
8923
8924         *info_p = info;
8925
8926         return WERR_OK;
8927 }
8928
8929 /****************************************************************
8930  _spoolss_EnumPrintProcDataTypes
8931 ****************************************************************/
8932
8933 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
8934                                        struct spoolss_EnumPrintProcDataTypes *r)
8935 {
8936         WERROR result;
8937
8938         /* that's an [in out] buffer */
8939
8940         if (!r->in.buffer && (r->in.offered != 0)) {
8941                 return WERR_INVALID_PARAM;
8942         }
8943
8944         DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8945
8946         *r->out.count = 0;
8947         *r->out.needed = 0;
8948         *r->out.info = NULL;
8949
8950         if (r->in.print_processor_name == NULL ||
8951             !strequal(r->in.print_processor_name, "winprint")) {
8952                 return WERR_UNKNOWN_PRINTPROCESSOR;
8953         }
8954
8955         switch (r->in.level) {
8956         case 1:
8957                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8958                                                         r->out.count);
8959                 break;
8960         default:
8961                 return WERR_UNKNOWN_LEVEL;
8962         }
8963
8964         if (!W_ERROR_IS_OK(result)) {
8965                 return result;
8966         }
8967
8968         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8969                                                      spoolss_EnumPrintProcDataTypes,
8970                                                      *r->out.info, r->in.level,
8971                                                      *r->out.count);
8972         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8973         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8974
8975         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8976 }
8977
8978 /****************************************************************************
8979  fill_monitor_1
8980 ****************************************************************************/
8981
8982 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8983                              struct spoolss_MonitorInfo1 *r,
8984                              const char *monitor_name)
8985 {
8986         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8987         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8988
8989         return WERR_OK;
8990 }
8991
8992 /****************************************************************************
8993  fill_monitor_2
8994 ****************************************************************************/
8995
8996 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8997                              struct spoolss_MonitorInfo2 *r,
8998                              const char *monitor_name,
8999                              const char *environment,
9000                              const char *dll_name)
9001 {
9002         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
9003         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9004         r->environment                  = talloc_strdup(mem_ctx, environment);
9005         W_ERROR_HAVE_NO_MEMORY(r->environment);
9006         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
9007         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
9008
9009         return WERR_OK;
9010 }
9011
9012 /****************************************************************************
9013  enumprintmonitors level 1.
9014 ****************************************************************************/
9015
9016 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
9017                                         union spoolss_MonitorInfo **info_p,
9018                                         uint32_t *count)
9019 {
9020         union spoolss_MonitorInfo *info;
9021         WERROR result = WERR_OK;
9022
9023         info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9024         W_ERROR_HAVE_NO_MEMORY(info);
9025
9026         *count = 2;
9027
9028         result = fill_monitor_1(info, &info[0].info1,
9029                                 SPL_LOCAL_PORT);
9030         if (!W_ERROR_IS_OK(result)) {
9031                 goto out;
9032         }
9033
9034         result = fill_monitor_1(info, &info[1].info1,
9035                                 SPL_TCPIP_PORT);
9036         if (!W_ERROR_IS_OK(result)) {
9037                 goto out;
9038         }
9039
9040 out:
9041         if (!W_ERROR_IS_OK(result)) {
9042                 TALLOC_FREE(info);
9043                 *count = 0;
9044                 return result;
9045         }
9046
9047         *info_p = info;
9048
9049         return WERR_OK;
9050 }
9051
9052 /****************************************************************************
9053  enumprintmonitors level 2.
9054 ****************************************************************************/
9055
9056 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
9057                                         union spoolss_MonitorInfo **info_p,
9058                                         uint32_t *count)
9059 {
9060         union spoolss_MonitorInfo *info;
9061         WERROR result = WERR_OK;
9062
9063         info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9064         W_ERROR_HAVE_NO_MEMORY(info);
9065
9066         *count = 2;
9067
9068         result = fill_monitor_2(info, &info[0].info2,
9069                                 SPL_LOCAL_PORT,
9070                                 "Windows NT X86", /* FIXME */
9071                                 "localmon.dll");
9072         if (!W_ERROR_IS_OK(result)) {
9073                 goto out;
9074         }
9075
9076         result = fill_monitor_2(info, &info[1].info2,
9077                                 SPL_TCPIP_PORT,
9078                                 "Windows NT X86", /* FIXME */
9079                                 "tcpmon.dll");
9080         if (!W_ERROR_IS_OK(result)) {
9081                 goto out;
9082         }
9083
9084 out:
9085         if (!W_ERROR_IS_OK(result)) {
9086                 TALLOC_FREE(info);
9087                 *count = 0;
9088                 return result;
9089         }
9090
9091         *info_p = info;
9092
9093         return WERR_OK;
9094 }
9095
9096 /****************************************************************
9097  _spoolss_EnumMonitors
9098 ****************************************************************/
9099
9100 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
9101                              struct spoolss_EnumMonitors *r)
9102 {
9103         WERROR result;
9104
9105         /* that's an [in out] buffer */
9106
9107         if (!r->in.buffer && (r->in.offered != 0)) {
9108                 return WERR_INVALID_PARAM;
9109         }
9110
9111         DEBUG(5,("_spoolss_EnumMonitors\n"));
9112
9113         /*
9114          * Enumerate the print monitors ...
9115          *
9116          * Just reply with "Local Port", to keep NT happy
9117          * and I can use my nice printer checker.
9118          */
9119
9120         *r->out.count = 0;
9121         *r->out.needed = 0;
9122         *r->out.info = NULL;
9123
9124         switch (r->in.level) {
9125         case 1:
9126                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
9127                                                    r->out.count);
9128                 break;
9129         case 2:
9130                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
9131                                                    r->out.count);
9132                 break;
9133         default:
9134                 return WERR_UNKNOWN_LEVEL;
9135         }
9136
9137         if (!W_ERROR_IS_OK(result)) {
9138                 return result;
9139         }
9140
9141         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9142                                                      spoolss_EnumMonitors,
9143                                                      *r->out.info, r->in.level,
9144                                                      *r->out.count);
9145         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9146         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9147
9148         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9149 }
9150
9151 /****************************************************************************
9152 ****************************************************************************/
9153
9154 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
9155                              const print_queue_struct *queue,
9156                              int count, int snum,
9157                              struct spoolss_PrinterInfo2 *pinfo2,
9158                              uint32_t jobid,
9159                              struct spoolss_JobInfo1 *r)
9160 {
9161         int i = 0;
9162         bool found = false;
9163
9164         for (i=0; i<count; i++) {
9165                 if (queue[i].job == (int)jobid) {
9166                         found = true;
9167                         break;
9168                 }
9169         }
9170
9171         if (found == false) {
9172                 /* NT treats not found as bad param... yet another bad choice */
9173                 return WERR_INVALID_PARAM;
9174         }
9175
9176         return fill_job_info1(mem_ctx,
9177                               r,
9178                               &queue[i],
9179                               i,
9180                               snum,
9181                               pinfo2);
9182 }
9183
9184 /****************************************************************************
9185 ****************************************************************************/
9186
9187 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9188                              const print_queue_struct *queue,
9189                              int count, int snum,
9190                              struct spoolss_PrinterInfo2 *pinfo2,
9191                              uint32_t jobid,
9192                              struct spoolss_JobInfo2 *r)
9193 {
9194         int i = 0;
9195         bool found = false;
9196         struct spoolss_DeviceMode *devmode;
9197         WERROR result;
9198
9199         for (i=0; i<count; i++) {
9200                 if (queue[i].job == (int)jobid) {
9201                         found = true;
9202                         break;
9203                 }
9204         }
9205
9206         if (found == false) {
9207                 /* NT treats not found as bad param... yet another bad
9208                    choice */
9209                 return WERR_INVALID_PARAM;
9210         }
9211
9212         /*
9213          * if the print job does not have a DEVMODE associated with it,
9214          * just use the one for the printer. A NULL devicemode is not
9215          *  a failure condition
9216          */
9217
9218         devmode = print_job_devmode(lp_const_servicename(snum), jobid);
9219         if (!devmode) {
9220                 result = spoolss_create_default_devmode(mem_ctx,
9221                                                 pinfo2->printername,
9222                                                 &devmode);
9223                 if (!W_ERROR_IS_OK(result)) {
9224                         DEBUG(3, ("Can't proceed w/o a devmode!"));
9225                         return result;
9226                 }
9227         }
9228
9229         return fill_job_info2(mem_ctx,
9230                               r,
9231                               &queue[i],
9232                               i,
9233                               snum,
9234                               pinfo2,
9235                               devmode);
9236 }
9237
9238 /****************************************************************
9239  _spoolss_GetJob
9240 ****************************************************************/
9241
9242 WERROR _spoolss_GetJob(struct pipes_struct *p,
9243                        struct spoolss_GetJob *r)
9244 {
9245         WERROR result = WERR_OK;
9246         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9247         int snum;
9248         int count;
9249         print_queue_struct      *queue = NULL;
9250         print_status_struct prt_status;
9251
9252         /* that's an [in out] buffer */
9253
9254         if (!r->in.buffer && (r->in.offered != 0)) {
9255                 return WERR_INVALID_PARAM;
9256         }
9257
9258         DEBUG(5,("_spoolss_GetJob\n"));
9259
9260         *r->out.needed = 0;
9261
9262         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9263                 return WERR_BADFID;
9264         }
9265
9266         result = winreg_get_printer_internal(p->mem_ctx,
9267                                     get_session_info_system(),
9268                                     p->msg_ctx,
9269                                     lp_const_servicename(snum),
9270                                     &pinfo2);
9271         if (!W_ERROR_IS_OK(result)) {
9272                 return result;
9273         }
9274
9275         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9276
9277         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9278                      count, prt_status.status, prt_status.message));
9279
9280         switch (r->in.level) {
9281         case 1:
9282                 result = getjob_level_1(p->mem_ctx,
9283                                         queue, count, snum, pinfo2,
9284                                         r->in.job_id, &r->out.info->info1);
9285                 break;
9286         case 2:
9287                 result = getjob_level_2(p->mem_ctx,
9288                                         queue, count, snum, pinfo2,
9289                                         r->in.job_id, &r->out.info->info2);
9290                 break;
9291         default:
9292                 result = WERR_UNKNOWN_LEVEL;
9293                 break;
9294         }
9295
9296         SAFE_FREE(queue);
9297         TALLOC_FREE(pinfo2);
9298
9299         if (!W_ERROR_IS_OK(result)) {
9300                 TALLOC_FREE(r->out.info);
9301                 return result;
9302         }
9303
9304         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9305                                                                                    r->in.level);
9306         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9307
9308         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9309 }
9310
9311 /****************************************************************
9312  _spoolss_GetPrinterDataEx
9313 ****************************************************************/
9314
9315 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9316                                  struct spoolss_GetPrinterDataEx *r)
9317 {
9318
9319         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9320         const char *printer;
9321         int                     snum = 0;
9322         WERROR result = WERR_OK;
9323         DATA_BLOB blob;
9324         enum winreg_Type val_type = REG_NONE;
9325         uint8_t *val_data = NULL;
9326         uint32_t val_size = 0;
9327         struct dcerpc_binding_handle *b;
9328         TALLOC_CTX *tmp_ctx;
9329
9330         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9331
9332         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9333                 r->in.key_name, r->in.value_name));
9334
9335         /* in case of problem, return some default values */
9336
9337         *r->out.needed  = 0;
9338         *r->out.type    = REG_NONE;
9339
9340         tmp_ctx = talloc_new(p->mem_ctx);
9341         if (!tmp_ctx) {
9342                 return WERR_NOMEM;
9343         }
9344
9345         if (!Printer) {
9346                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9347                         OUR_HANDLE(r->in.handle)));
9348                 result = WERR_BADFID;
9349                 goto done;
9350         }
9351
9352         /* check to see if the keyname is valid */
9353         if (!strlen(r->in.key_name)) {
9354                 result = WERR_INVALID_PARAM;
9355                 goto done;
9356         }
9357
9358         /* Is the handle to a printer or to the server? */
9359
9360         if (Printer->printer_type == SPLHND_SERVER) {
9361
9362                 union spoolss_PrinterData data;
9363
9364                 result = getprinterdata_printer_server(tmp_ctx,
9365                                                        r->in.value_name,
9366                                                        r->out.type,
9367                                                        &data);
9368                 if (!W_ERROR_IS_OK(result)) {
9369                         goto done;
9370                 }
9371
9372                 result = push_spoolss_PrinterData(tmp_ctx, &blob,
9373                                                   *r->out.type, &data);
9374                 if (!W_ERROR_IS_OK(result)) {
9375                         goto done;
9376                 }
9377
9378                 *r->out.needed = blob.length;
9379
9380                 if (r->in.offered >= *r->out.needed) {
9381                         memcpy(r->out.data, blob.data, blob.length);
9382                 }
9383
9384                 result = WERR_OK;
9385                 goto done;
9386         }
9387
9388         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9389                 result = WERR_BADFID;
9390                 goto done;
9391         }
9392         printer = lp_const_servicename(snum);
9393
9394         result = winreg_printer_binding_handle(tmp_ctx,
9395                                                get_session_info_system(),
9396                                                p->msg_ctx,
9397                                                &b);
9398         if (!W_ERROR_IS_OK(result)) {
9399                 goto done;
9400         }
9401
9402         /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9403         if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9404             strequal(r->in.value_name, "ChangeId")) {
9405                 *r->out.type = REG_DWORD;
9406                 *r->out.needed = 4;
9407                 if (r->in.offered >= *r->out.needed) {
9408                         uint32_t changeid = 0;
9409
9410                         result = winreg_printer_get_changeid(tmp_ctx, b,
9411                                                              printer,
9412                                                              &changeid);
9413                         if (!W_ERROR_IS_OK(result)) {
9414                                 goto done;
9415                         }
9416
9417                         SIVAL(r->out.data, 0, changeid);
9418                         result = WERR_OK;
9419                 }
9420                 goto done;
9421         }
9422
9423         result = winreg_get_printer_dataex(tmp_ctx, b,
9424                                            printer,
9425                                            r->in.key_name,
9426                                            r->in.value_name,
9427                                            &val_type,
9428                                            &val_data,
9429                                            &val_size);
9430         if (!W_ERROR_IS_OK(result)) {
9431                 goto done;
9432         }
9433
9434         *r->out.needed = val_size;
9435         *r->out.type = val_type;
9436
9437         if (r->in.offered >= *r->out.needed) {
9438                 memcpy(r->out.data, val_data, val_size);
9439         }
9440
9441 done:
9442         /* NOTE: do not replace type when returning WERR_MORE_DATA */
9443
9444         if (W_ERROR_IS_OK(result)) {
9445                 result = SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9446         }
9447
9448         talloc_free(tmp_ctx);
9449         return result;
9450 }
9451
9452 /****************************************************************
9453  _spoolss_SetPrinterDataEx
9454 ****************************************************************/
9455
9456 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9457                                  struct spoolss_SetPrinterDataEx *r)
9458 {
9459         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9460         int                     snum = 0;
9461         WERROR                  result = WERR_OK;
9462         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9463         char                    *oid_string;
9464         struct dcerpc_binding_handle *b;
9465         TALLOC_CTX *tmp_ctx;
9466
9467         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9468
9469         /* From MSDN documentation of SetPrinterDataEx: pass request to
9470            SetPrinterData if key is "PrinterDriverData" */
9471
9472         if (!Printer) {
9473                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9474                         OUR_HANDLE(r->in.handle)));
9475                 return WERR_BADFID;
9476         }
9477
9478         if (Printer->printer_type == SPLHND_SERVER) {
9479                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9480                         "Not implemented for server handles yet\n"));
9481                 return WERR_INVALID_PARAM;
9482         }
9483
9484         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9485                 return WERR_BADFID;
9486         }
9487
9488         /*
9489          * Access check : NT returns "access denied" if you make a
9490          * SetPrinterData call without the necessary privildge.
9491          * we were originally returning OK if nothing changed
9492          * which made Win2k issue **a lot** of SetPrinterData
9493          * when connecting to a printer  --jerry
9494          */
9495
9496         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9497                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9498                         "change denied by handle access permissions\n"));
9499                 return WERR_ACCESS_DENIED;
9500         }
9501
9502         tmp_ctx = talloc_new(p->mem_ctx);
9503         if (!tmp_ctx) {
9504                 return WERR_NOMEM;
9505         }
9506
9507         result = winreg_printer_binding_handle(tmp_ctx,
9508                                                get_session_info_system(),
9509                                                p->msg_ctx,
9510                                                &b);
9511         if (!W_ERROR_IS_OK(result)) {
9512                 goto done;
9513         }
9514
9515         result = winreg_get_printer(tmp_ctx, b,
9516                                     lp_servicename(snum),
9517                                     &pinfo2);
9518         if (!W_ERROR_IS_OK(result)) {
9519                 goto done;
9520         }
9521
9522         /* check for OID in valuename */
9523
9524         oid_string = strchr(r->in.value_name, ',');
9525         if (oid_string) {
9526                 *oid_string = '\0';
9527                 oid_string++;
9528         }
9529
9530         /* save the registry data */
9531
9532         result = winreg_set_printer_dataex(tmp_ctx, b,
9533                                            pinfo2->sharename,
9534                                            r->in.key_name,
9535                                            r->in.value_name,
9536                                            r->in.type,
9537                                            r->in.data,
9538                                            r->in.offered);
9539
9540         if (W_ERROR_IS_OK(result)) {
9541                 /* save the OID if one was specified */
9542                 if (oid_string) {
9543                         char *str = talloc_asprintf(tmp_ctx, "%s\\%s",
9544                                 r->in.key_name, SPOOL_OID_KEY);
9545                         if (!str) {
9546                                 result = WERR_NOMEM;
9547                                 goto done;
9548                         }
9549
9550                         /*
9551                          * I'm not checking the status here on purpose.  Don't know
9552                          * if this is right, but I'm returning the status from the
9553                          * previous set_printer_dataex() call.  I have no idea if
9554                          * this is right.    --jerry
9555                          */
9556                         winreg_set_printer_dataex(tmp_ctx, b,
9557                                                   pinfo2->sharename,
9558                                                   str,
9559                                                   r->in.value_name,
9560                                                   REG_SZ,
9561                                                   (uint8_t *) oid_string,
9562                                                   strlen(oid_string) + 1);
9563                 }
9564
9565                 result = winreg_printer_update_changeid(tmp_ctx, b,
9566                                                         lp_const_servicename(snum));
9567
9568         }
9569
9570 done:
9571         talloc_free(tmp_ctx);
9572         return result;
9573 }
9574
9575 /****************************************************************
9576  _spoolss_DeletePrinterDataEx
9577 ****************************************************************/
9578
9579 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9580                                     struct spoolss_DeletePrinterDataEx *r)
9581 {
9582         const char *printer;
9583         int             snum=0;
9584         WERROR          status = WERR_OK;
9585         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9586
9587         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9588
9589         if (!Printer) {
9590                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9591                         "Invalid handle (%s:%u:%u).\n",
9592                         OUR_HANDLE(r->in.handle)));
9593                 return WERR_BADFID;
9594         }
9595
9596         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9597                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9598                         "printer properties change denied by handle\n"));
9599                 return WERR_ACCESS_DENIED;
9600         }
9601
9602         if (!r->in.value_name || !r->in.key_name) {
9603                 return WERR_NOMEM;
9604         }
9605
9606         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9607                 return WERR_BADFID;
9608         }
9609         printer = lp_const_servicename(snum);
9610
9611         status = winreg_delete_printer_dataex_internal(p->mem_ctx,
9612                                               get_session_info_system(),
9613                                               p->msg_ctx,
9614                                               printer,
9615                                               r->in.key_name,
9616                                               r->in.value_name);
9617         if (W_ERROR_IS_OK(status)) {
9618                 status = winreg_printer_update_changeid_internal(p->mem_ctx,
9619                                                         get_session_info_system(),
9620                                                         p->msg_ctx,
9621                                                         printer);
9622         }
9623
9624         return status;
9625 }
9626
9627 /****************************************************************
9628  _spoolss_EnumPrinterKey
9629 ****************************************************************/
9630
9631 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9632                                struct spoolss_EnumPrinterKey *r)
9633 {
9634         uint32_t        num_keys;
9635         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9636         int             snum = 0;
9637         WERROR          result = WERR_BADFILE;
9638         const char **array = NULL;
9639         DATA_BLOB blob;
9640
9641         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9642
9643         if (!Printer) {
9644                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9645                         OUR_HANDLE(r->in.handle)));
9646                 return WERR_BADFID;
9647         }
9648
9649         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9650                 return WERR_BADFID;
9651         }
9652
9653         result = winreg_enum_printer_key_internal(p->mem_ctx,
9654                                          get_session_info_system(),
9655                                          p->msg_ctx,
9656                                          lp_const_servicename(snum),
9657                                          r->in.key_name,
9658                                          &num_keys,
9659                                          &array);
9660         if (!W_ERROR_IS_OK(result)) {
9661                 goto done;
9662         }
9663
9664         if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9665                 result = WERR_NOMEM;
9666                 goto done;
9667         }
9668
9669         *r->out._ndr_size = r->in.offered / 2;
9670         *r->out.needed = blob.length;
9671
9672         if (r->in.offered < *r->out.needed) {
9673                 result = WERR_MORE_DATA;
9674         } else {
9675                 result = WERR_OK;
9676                 r->out.key_buffer->string_array = array;
9677         }
9678
9679  done:
9680         if (!W_ERROR_IS_OK(result)) {
9681                 TALLOC_FREE(array);
9682                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9683                         *r->out.needed = 0;
9684                 }
9685         }
9686
9687         return result;
9688 }
9689
9690 /****************************************************************
9691  _spoolss_DeletePrinterKey
9692 ****************************************************************/
9693
9694 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9695                                  struct spoolss_DeletePrinterKey *r)
9696 {
9697         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9698         int                     snum=0;
9699         WERROR                  status;
9700         const char *printer;
9701         struct dcerpc_binding_handle *b;
9702         TALLOC_CTX *tmp_ctx;
9703
9704         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9705
9706         if (!Printer) {
9707                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9708                         OUR_HANDLE(r->in.handle)));
9709                 return WERR_BADFID;
9710         }
9711
9712         /* if keyname == NULL, return error */
9713         if ( !r->in.key_name )
9714                 return WERR_INVALID_PARAM;
9715
9716         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9717                 return WERR_BADFID;
9718         }
9719
9720         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9721                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9722                         "printer properties change denied by handle\n"));
9723                 return WERR_ACCESS_DENIED;
9724         }
9725
9726         printer = lp_const_servicename(snum);
9727
9728         tmp_ctx = talloc_new(p->mem_ctx);
9729         if (!tmp_ctx) {
9730                 return WERR_NOMEM;
9731         }
9732
9733         status = winreg_printer_binding_handle(tmp_ctx,
9734                                                get_session_info_system(),
9735                                                p->msg_ctx,
9736                                                &b);
9737         if (!W_ERROR_IS_OK(status)) {
9738                 goto done;
9739         }
9740
9741         /* delete the key and all subkeys */
9742         status = winreg_delete_printer_key(tmp_ctx, b,
9743                                            printer,
9744                                            r->in.key_name);
9745         if (W_ERROR_IS_OK(status)) {
9746                 status = winreg_printer_update_changeid(tmp_ctx, b,
9747                                                         printer);
9748         }
9749
9750 done:
9751         talloc_free(tmp_ctx);
9752         return status;
9753 }
9754
9755 /****************************************************************
9756  _spoolss_EnumPrinterDataEx
9757 ****************************************************************/
9758
9759 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
9760                                   struct spoolss_EnumPrinterDataEx *r)
9761 {
9762         uint32_t        count = 0;
9763         struct spoolss_PrinterEnumValues *info = NULL;
9764         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9765         int             snum;
9766         WERROR          result;
9767
9768         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9769
9770         *r->out.count = 0;
9771         *r->out.needed = 0;
9772         *r->out.info = NULL;
9773
9774         if (!Printer) {
9775                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9776                         OUR_HANDLE(r->in.handle)));
9777                 return WERR_BADFID;
9778         }
9779
9780         /*
9781          * first check for a keyname of NULL or "".  Win2k seems to send
9782          * this a lot and we should send back WERR_INVALID_PARAM
9783          * no need to spend time looking up the printer in this case.
9784          * --jerry
9785          */
9786
9787         if (!strlen(r->in.key_name)) {
9788                 result = WERR_INVALID_PARAM;
9789                 goto done;
9790         }
9791
9792         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9793                 return WERR_BADFID;
9794         }
9795
9796         /* now look for a match on the key name */
9797         result = winreg_enum_printer_dataex_internal(p->mem_ctx,
9798                                             get_session_info_system(),
9799                                             p->msg_ctx,
9800                                             lp_const_servicename(snum),
9801                                             r->in.key_name,
9802                                             &count,
9803                                             &info);
9804         if (!W_ERROR_IS_OK(result)) {
9805                 goto done;
9806         }
9807
9808 #if 0 /* FIXME - gd */
9809         /* housekeeping information in the reply */
9810
9811         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9812          * the hand marshalled container size is a multiple
9813          * of 4 bytes for RPC alignment.
9814          */
9815
9816         if (needed % 4) {
9817                 needed += 4-(needed % 4);
9818         }
9819 #endif
9820         *r->out.count   = count;
9821         *r->out.info    = info;
9822
9823  done:
9824         if (!W_ERROR_IS_OK(result)) {
9825                 return result;
9826         }
9827
9828         *r->out.needed  = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9829                                                spoolss_EnumPrinterDataEx,
9830                                                *r->out.info,
9831                                                *r->out.count);
9832         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9833         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9834
9835         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9836 }
9837
9838 /****************************************************************************
9839 ****************************************************************************/
9840
9841 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9842                                                  const char *servername,
9843                                                  const char *environment,
9844                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
9845 {
9846         WERROR werr;
9847         char *path = NULL;
9848
9849         werr = compose_spoolss_server_path(mem_ctx,
9850                                            servername,
9851                                            environment,
9852                                            SPOOLSS_PRTPROCS_PATH,
9853                                            &path);
9854         if (!W_ERROR_IS_OK(werr)) {
9855                 return werr;
9856         }
9857
9858         DEBUG(4,("print processor directory: [%s]\n", path));
9859
9860         r->directory_name = path;
9861
9862         return WERR_OK;
9863 }
9864
9865 /****************************************************************
9866  _spoolss_GetPrintProcessorDirectory
9867 ****************************************************************/
9868
9869 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
9870                                            struct spoolss_GetPrintProcessorDirectory *r)
9871 {
9872         WERROR result;
9873         char *prnproc_share = NULL;
9874         bool prnproc_share_exists = false;
9875         int snum;
9876
9877         /* that's an [in out] buffer */
9878
9879         if (!r->in.buffer && (r->in.offered != 0)) {
9880                 return WERR_INVALID_PARAM;
9881         }
9882
9883         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9884                 r->in.level));
9885
9886         *r->out.needed = 0;
9887
9888         /* r->in.level is ignored */
9889
9890         /* We always should reply with a local print processor directory so that
9891          * users are not forced to have a [prnproc$] share on the Samba spoolss
9892          * server, if users decide to do so, lets announce it though - Guenther */
9893
9894         snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
9895         if (!prnproc_share) {
9896                 return WERR_NOMEM;
9897         }
9898         if (snum != -1) {
9899                 prnproc_share_exists = true;
9900         }
9901
9902         result = getprintprocessordirectory_level_1(p->mem_ctx,
9903                                                     prnproc_share_exists ? r->in.server : NULL,
9904                                                     r->in.environment,
9905                                                     &r->out.info->info1);
9906         if (!W_ERROR_IS_OK(result)) {
9907                 TALLOC_FREE(r->out.info);
9908                 return result;
9909         }
9910
9911         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
9912                                                                                    r->out.info, r->in.level);
9913         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9914
9915         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9916 }
9917
9918 /*******************************************************************
9919  ********************************************************************/
9920
9921 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9922                                const char *dllname)
9923 {
9924         enum ndr_err_code ndr_err;
9925         struct spoolss_MonitorUi ui;
9926
9927         ui.dll_name = dllname;
9928
9929         ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
9930                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9931         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9932                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9933         }
9934         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9935 }
9936
9937 /*******************************************************************
9938  Streams the monitor UI DLL name in UNICODE
9939 *******************************************************************/
9940
9941 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9942                                struct security_token *token, DATA_BLOB *in,
9943                                DATA_BLOB *out, uint32_t *needed)
9944 {
9945         const char *dllname = "tcpmonui.dll";
9946
9947         *needed = (strlen(dllname)+1) * 2;
9948
9949         if (out->length < *needed) {
9950                 return WERR_INSUFFICIENT_BUFFER;
9951         }
9952
9953         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9954                 return WERR_NOMEM;
9955         }
9956
9957         return WERR_OK;
9958 }
9959
9960 /*******************************************************************
9961  ********************************************************************/
9962
9963 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9964                              struct spoolss_PortData1 *port1,
9965                              const DATA_BLOB *buf)
9966 {
9967         enum ndr_err_code ndr_err;
9968         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
9969                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9970         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9971                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9972         }
9973         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9974 }
9975
9976 /*******************************************************************
9977  ********************************************************************/
9978
9979 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9980                              struct spoolss_PortData2 *port2,
9981                              const DATA_BLOB *buf)
9982 {
9983         enum ndr_err_code ndr_err;
9984         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
9985                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9986         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9987                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9988         }
9989         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9990 }
9991
9992 /*******************************************************************
9993  Create a new TCP/IP port
9994 *******************************************************************/
9995
9996 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9997                              struct security_token *token, DATA_BLOB *in,
9998                              DATA_BLOB *out, uint32_t *needed)
9999 {
10000         struct spoolss_PortData1 port1;
10001         struct spoolss_PortData2 port2;
10002         char *device_uri = NULL;
10003         uint32_t version;
10004
10005         const char *portname;
10006         const char *hostaddress;
10007         const char *queue;
10008         uint32_t port_number;
10009         uint32_t protocol;
10010
10011         /* peek for spoolss_PortData version */
10012
10013         if (!in || (in->length < (128 + 4))) {
10014                 return WERR_GENERAL_FAILURE;
10015         }
10016
10017         version = IVAL(in->data, 128);
10018
10019         switch (version) {
10020                 case 1:
10021                         ZERO_STRUCT(port1);
10022
10023                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
10024                                 return WERR_NOMEM;
10025                         }
10026
10027                         portname        = port1.portname;
10028                         hostaddress     = port1.hostaddress;
10029                         queue           = port1.queue;
10030                         protocol        = port1.protocol;
10031                         port_number     = port1.port_number;
10032
10033                         break;
10034                 case 2:
10035                         ZERO_STRUCT(port2);
10036
10037                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
10038                                 return WERR_NOMEM;
10039                         }
10040
10041                         portname        = port2.portname;
10042                         hostaddress     = port2.hostaddress;
10043                         queue           = port2.queue;
10044                         protocol        = port2.protocol;
10045                         port_number     = port2.port_number;
10046
10047                         break;
10048                 default:
10049                         DEBUG(1,("xcvtcp_addport: "
10050                                 "unknown version of port_data: %d\n", version));
10051                         return WERR_UNKNOWN_PORT;
10052         }
10053
10054         /* create the device URI and call the add_port_hook() */
10055
10056         switch (protocol) {
10057         case PROTOCOL_RAWTCP_TYPE:
10058                 device_uri = talloc_asprintf(mem_ctx,
10059                                 "socket://%s:%d/", hostaddress,
10060                                 port_number);
10061                 break;
10062
10063         case PROTOCOL_LPR_TYPE:
10064                 device_uri = talloc_asprintf(mem_ctx,
10065                         "lpr://%s/%s", hostaddress, queue );
10066                 break;
10067
10068         default:
10069                 return WERR_UNKNOWN_PORT;
10070         }
10071
10072         if (!device_uri) {
10073                 return WERR_NOMEM;
10074         }
10075
10076         return add_port_hook(mem_ctx, token, portname, device_uri);
10077 }
10078
10079 /*******************************************************************
10080 *******************************************************************/
10081
10082 struct xcv_api_table xcvtcp_cmds[] = {
10083         { "MonitorUI",  xcvtcp_monitorui },
10084         { "AddPort",    xcvtcp_addport},
10085         { NULL,         NULL }
10086 };
10087
10088 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
10089                                      struct security_token *token, const char *command,
10090                                      DATA_BLOB *inbuf,
10091                                      DATA_BLOB *outbuf,
10092                                      uint32_t *needed )
10093 {
10094         int i;
10095
10096         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
10097
10098         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
10099                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
10100                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10101         }
10102
10103         return WERR_BADFUNC;
10104 }
10105
10106 /*******************************************************************
10107 *******************************************************************/
10108 #if 0   /* don't support management using the "Local Port" monitor */
10109
10110 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
10111                                  struct security_token *token, DATA_BLOB *in,
10112                                  DATA_BLOB *out, uint32_t *needed)
10113 {
10114         const char *dllname = "localui.dll";
10115
10116         *needed = (strlen(dllname)+1) * 2;
10117
10118         if (out->length < *needed) {
10119                 return WERR_INSUFFICIENT_BUFFER;
10120         }
10121
10122         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10123                 return WERR_NOMEM;
10124         }
10125
10126         return WERR_OK;
10127 }
10128
10129 /*******************************************************************
10130 *******************************************************************/
10131
10132 struct xcv_api_table xcvlocal_cmds[] = {
10133         { "MonitorUI",  xcvlocal_monitorui },
10134         { NULL,         NULL }
10135 };
10136 #else
10137 struct xcv_api_table xcvlocal_cmds[] = {
10138         { NULL,         NULL }
10139 };
10140 #endif
10141
10142
10143
10144 /*******************************************************************
10145 *******************************************************************/
10146
10147 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
10148                                        struct security_token *token, const char *command,
10149                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
10150                                        uint32_t *needed)
10151 {
10152         int i;
10153
10154         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10155
10156         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10157                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10158                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10159         }
10160         return WERR_BADFUNC;
10161 }
10162
10163 /****************************************************************
10164  _spoolss_XcvData
10165 ****************************************************************/
10166
10167 WERROR _spoolss_XcvData(struct pipes_struct *p,
10168                         struct spoolss_XcvData *r)
10169 {
10170         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10171         DATA_BLOB out_data = data_blob_null;
10172         WERROR werror;
10173
10174         if (!Printer) {
10175                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10176                         OUR_HANDLE(r->in.handle)));
10177                 return WERR_BADFID;
10178         }
10179
10180         /* Has to be a handle to the TCP/IP port monitor */
10181
10182         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10183                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10184                 return WERR_BADFID;
10185         }
10186
10187         /* requires administrative access to the server */
10188
10189         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10190                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10191                 return WERR_ACCESS_DENIED;
10192         }
10193
10194         /* Allocate the outgoing buffer */
10195
10196         if (r->in.out_data_size) {
10197                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10198                 if (out_data.data == NULL) {
10199                         return WERR_NOMEM;
10200                 }
10201         }
10202
10203         switch ( Printer->printer_type ) {
10204         case SPLHND_PORTMON_TCP:
10205                 werror = process_xcvtcp_command(p->mem_ctx,
10206                                                 p->session_info->security_token,
10207                                                 r->in.function_name,
10208                                                 &r->in.in_data, &out_data,
10209                                                 r->out.needed);
10210                 break;
10211         case SPLHND_PORTMON_LOCAL:
10212                 werror = process_xcvlocal_command(p->mem_ctx,
10213                                                   p->session_info->security_token,
10214                                                   r->in.function_name,
10215                                                   &r->in.in_data, &out_data,
10216                                                   r->out.needed);
10217                 break;
10218         default:
10219                 werror = WERR_INVALID_PRINT_MONITOR;
10220         }
10221
10222         if (!W_ERROR_IS_OK(werror)) {
10223                 return werror;
10224         }
10225
10226         *r->out.status_code = 0;
10227
10228         if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10229                 memcpy(r->out.out_data, out_data.data,
10230                         MIN(r->in.out_data_size, out_data.length));
10231         }
10232
10233         return WERR_OK;
10234 }
10235
10236 /****************************************************************
10237  _spoolss_AddPrintProcessor
10238 ****************************************************************/
10239
10240 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10241                                   struct spoolss_AddPrintProcessor *r)
10242 {
10243         /* for now, just indicate success and ignore the add.  We'll
10244            automatically set the winprint processor for printer
10245            entries later.  Used to debug the LexMark Optra S 1855 PCL
10246            driver --jerry */
10247
10248         return WERR_OK;
10249 }
10250
10251 /****************************************************************
10252  _spoolss_AddPort
10253 ****************************************************************/
10254
10255 WERROR _spoolss_AddPort(struct pipes_struct *p,
10256                         struct spoolss_AddPort *r)
10257 {
10258         /* do what w2k3 does */
10259
10260         return WERR_NOT_SUPPORTED;
10261 }
10262
10263 /****************************************************************
10264  _spoolss_GetPrinterDriver
10265 ****************************************************************/
10266
10267 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10268                                  struct spoolss_GetPrinterDriver *r)
10269 {
10270         p->rng_fault_state = true;
10271         return WERR_NOT_SUPPORTED;
10272 }
10273
10274 /****************************************************************
10275  _spoolss_ReadPrinter
10276 ****************************************************************/
10277
10278 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10279                             struct spoolss_ReadPrinter *r)
10280 {
10281         p->rng_fault_state = true;
10282         return WERR_NOT_SUPPORTED;
10283 }
10284
10285 /****************************************************************
10286  _spoolss_WaitForPrinterChange
10287 ****************************************************************/
10288
10289 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10290                                      struct spoolss_WaitForPrinterChange *r)
10291 {
10292         p->rng_fault_state = true;
10293         return WERR_NOT_SUPPORTED;
10294 }
10295
10296 /****************************************************************
10297  _spoolss_ConfigurePort
10298 ****************************************************************/
10299
10300 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10301                               struct spoolss_ConfigurePort *r)
10302 {
10303         p->rng_fault_state = true;
10304         return WERR_NOT_SUPPORTED;
10305 }
10306
10307 /****************************************************************
10308  _spoolss_DeletePort
10309 ****************************************************************/
10310
10311 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10312                            struct spoolss_DeletePort *r)
10313 {
10314         p->rng_fault_state = true;
10315         return WERR_NOT_SUPPORTED;
10316 }
10317
10318 /****************************************************************
10319  _spoolss_CreatePrinterIC
10320 ****************************************************************/
10321
10322 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10323                                 struct spoolss_CreatePrinterIC *r)
10324 {
10325         p->rng_fault_state = true;
10326         return WERR_NOT_SUPPORTED;
10327 }
10328
10329 /****************************************************************
10330  _spoolss_PlayGDIScriptOnPrinterIC
10331 ****************************************************************/
10332
10333 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10334                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
10335 {
10336         p->rng_fault_state = true;
10337         return WERR_NOT_SUPPORTED;
10338 }
10339
10340 /****************************************************************
10341  _spoolss_DeletePrinterIC
10342 ****************************************************************/
10343
10344 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10345                                 struct spoolss_DeletePrinterIC *r)
10346 {
10347         p->rng_fault_state = true;
10348         return WERR_NOT_SUPPORTED;
10349 }
10350
10351 /****************************************************************
10352  _spoolss_AddPrinterConnection
10353 ****************************************************************/
10354
10355 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10356                                      struct spoolss_AddPrinterConnection *r)
10357 {
10358         p->rng_fault_state = true;
10359         return WERR_NOT_SUPPORTED;
10360 }
10361
10362 /****************************************************************
10363  _spoolss_DeletePrinterConnection
10364 ****************************************************************/
10365
10366 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10367                                         struct spoolss_DeletePrinterConnection *r)
10368 {
10369         p->rng_fault_state = true;
10370         return WERR_NOT_SUPPORTED;
10371 }
10372
10373 /****************************************************************
10374  _spoolss_PrinterMessageBox
10375 ****************************************************************/
10376
10377 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10378                                   struct spoolss_PrinterMessageBox *r)
10379 {
10380         p->rng_fault_state = true;
10381         return WERR_NOT_SUPPORTED;
10382 }
10383
10384 /****************************************************************
10385  _spoolss_AddMonitor
10386 ****************************************************************/
10387
10388 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10389                            struct spoolss_AddMonitor *r)
10390 {
10391         p->rng_fault_state = true;
10392         return WERR_NOT_SUPPORTED;
10393 }
10394
10395 /****************************************************************
10396  _spoolss_DeleteMonitor
10397 ****************************************************************/
10398
10399 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10400                               struct spoolss_DeleteMonitor *r)
10401 {
10402         p->rng_fault_state = true;
10403         return WERR_NOT_SUPPORTED;
10404 }
10405
10406 /****************************************************************
10407  _spoolss_DeletePrintProcessor
10408 ****************************************************************/
10409
10410 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10411                                      struct spoolss_DeletePrintProcessor *r)
10412 {
10413         p->rng_fault_state = true;
10414         return WERR_NOT_SUPPORTED;
10415 }
10416
10417 /****************************************************************
10418  _spoolss_AddPrintProvidor
10419 ****************************************************************/
10420
10421 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10422                                  struct spoolss_AddPrintProvidor *r)
10423 {
10424         p->rng_fault_state = true;
10425         return WERR_NOT_SUPPORTED;
10426 }
10427
10428 /****************************************************************
10429  _spoolss_DeletePrintProvidor
10430 ****************************************************************/
10431
10432 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10433                                     struct spoolss_DeletePrintProvidor *r)
10434 {
10435         p->rng_fault_state = true;
10436         return WERR_NOT_SUPPORTED;
10437 }
10438
10439 /****************************************************************
10440  _spoolss_FindFirstPrinterChangeNotification
10441 ****************************************************************/
10442
10443 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10444                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
10445 {
10446         p->rng_fault_state = true;
10447         return WERR_NOT_SUPPORTED;
10448 }
10449
10450 /****************************************************************
10451  _spoolss_FindNextPrinterChangeNotification
10452 ****************************************************************/
10453
10454 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10455                                                   struct spoolss_FindNextPrinterChangeNotification *r)
10456 {
10457         p->rng_fault_state = true;
10458         return WERR_NOT_SUPPORTED;
10459 }
10460
10461 /****************************************************************
10462  _spoolss_RouterFindFirstPrinterChangeNotificationOld
10463 ****************************************************************/
10464
10465 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10466                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10467 {
10468         p->rng_fault_state = true;
10469         return WERR_NOT_SUPPORTED;
10470 }
10471
10472 /****************************************************************
10473  _spoolss_ReplyOpenPrinter
10474 ****************************************************************/
10475
10476 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10477                                  struct spoolss_ReplyOpenPrinter *r)
10478 {
10479         p->rng_fault_state = true;
10480         return WERR_NOT_SUPPORTED;
10481 }
10482
10483 /****************************************************************
10484  _spoolss_RouterReplyPrinter
10485 ****************************************************************/
10486
10487 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10488                                    struct spoolss_RouterReplyPrinter *r)
10489 {
10490         p->rng_fault_state = true;
10491         return WERR_NOT_SUPPORTED;
10492 }
10493
10494 /****************************************************************
10495  _spoolss_ReplyClosePrinter
10496 ****************************************************************/
10497
10498 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10499                                   struct spoolss_ReplyClosePrinter *r)
10500 {
10501         p->rng_fault_state = true;
10502         return WERR_NOT_SUPPORTED;
10503 }
10504
10505 /****************************************************************
10506  _spoolss_AddPortEx
10507 ****************************************************************/
10508
10509 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10510                           struct spoolss_AddPortEx *r)
10511 {
10512         p->rng_fault_state = true;
10513         return WERR_NOT_SUPPORTED;
10514 }
10515
10516 /****************************************************************
10517  _spoolss_RouterFindFirstPrinterChangeNotification
10518 ****************************************************************/
10519
10520 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10521                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10522 {
10523         p->rng_fault_state = true;
10524         return WERR_NOT_SUPPORTED;
10525 }
10526
10527 /****************************************************************
10528  _spoolss_SpoolerInit
10529 ****************************************************************/
10530
10531 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10532                             struct spoolss_SpoolerInit *r)
10533 {
10534         p->rng_fault_state = true;
10535         return WERR_NOT_SUPPORTED;
10536 }
10537
10538 /****************************************************************
10539  _spoolss_ResetPrinterEx
10540 ****************************************************************/
10541
10542 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10543                                struct spoolss_ResetPrinterEx *r)
10544 {
10545         p->rng_fault_state = true;
10546         return WERR_NOT_SUPPORTED;
10547 }
10548
10549 /****************************************************************
10550  _spoolss_RouterReplyPrinterEx
10551 ****************************************************************/
10552
10553 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10554                                      struct spoolss_RouterReplyPrinterEx *r)
10555 {
10556         p->rng_fault_state = true;
10557         return WERR_NOT_SUPPORTED;
10558 }
10559
10560 /****************************************************************
10561  _spoolss_44
10562 ****************************************************************/
10563
10564 WERROR _spoolss_44(struct pipes_struct *p,
10565                    struct spoolss_44 *r)
10566 {
10567         p->rng_fault_state = true;
10568         return WERR_NOT_SUPPORTED;
10569 }
10570
10571 /****************************************************************
10572  _spoolss_SetPort
10573 ****************************************************************/
10574
10575 WERROR _spoolss_SetPort(struct pipes_struct *p,
10576                         struct spoolss_SetPort *r)
10577 {
10578         p->rng_fault_state = true;
10579         return WERR_NOT_SUPPORTED;
10580 }
10581
10582 /****************************************************************
10583  _spoolss_4a
10584 ****************************************************************/
10585
10586 WERROR _spoolss_4a(struct pipes_struct *p,
10587                    struct spoolss_4a *r)
10588 {
10589         p->rng_fault_state = true;
10590         return WERR_NOT_SUPPORTED;
10591 }
10592
10593 /****************************************************************
10594  _spoolss_4b
10595 ****************************************************************/
10596
10597 WERROR _spoolss_4b(struct pipes_struct *p,
10598                    struct spoolss_4b *r)
10599 {
10600         p->rng_fault_state = true;
10601         return WERR_NOT_SUPPORTED;
10602 }
10603
10604 /****************************************************************
10605  _spoolss_4c
10606 ****************************************************************/
10607
10608 WERROR _spoolss_4c(struct pipes_struct *p,
10609                    struct spoolss_4c *r)
10610 {
10611         p->rng_fault_state = true;
10612         return WERR_NOT_SUPPORTED;
10613 }
10614
10615 /****************************************************************
10616  _spoolss_53
10617 ****************************************************************/
10618
10619 WERROR _spoolss_53(struct pipes_struct *p,
10620                    struct spoolss_53 *r)
10621 {
10622         p->rng_fault_state = true;
10623         return WERR_NOT_SUPPORTED;
10624 }
10625
10626 /****************************************************************
10627  _spoolss_AddPerMachineConnection
10628 ****************************************************************/
10629
10630 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
10631                                         struct spoolss_AddPerMachineConnection *r)
10632 {
10633         p->rng_fault_state = true;
10634         return WERR_NOT_SUPPORTED;
10635 }
10636
10637 /****************************************************************
10638  _spoolss_DeletePerMachineConnection
10639 ****************************************************************/
10640
10641 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
10642                                            struct spoolss_DeletePerMachineConnection *r)
10643 {
10644         p->rng_fault_state = true;
10645         return WERR_NOT_SUPPORTED;
10646 }
10647
10648 /****************************************************************
10649  _spoolss_EnumPerMachineConnections
10650 ****************************************************************/
10651
10652 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
10653                                           struct spoolss_EnumPerMachineConnections *r)
10654 {
10655         p->rng_fault_state = true;
10656         return WERR_NOT_SUPPORTED;
10657 }
10658
10659 /****************************************************************
10660  _spoolss_5a
10661 ****************************************************************/
10662
10663 WERROR _spoolss_5a(struct pipes_struct *p,
10664                    struct spoolss_5a *r)
10665 {
10666         p->rng_fault_state = true;
10667         return WERR_NOT_SUPPORTED;
10668 }
10669
10670 /****************************************************************
10671  _spoolss_5b
10672 ****************************************************************/
10673
10674 WERROR _spoolss_5b(struct pipes_struct *p,
10675                    struct spoolss_5b *r)
10676 {
10677         p->rng_fault_state = true;
10678         return WERR_NOT_SUPPORTED;
10679 }
10680
10681 /****************************************************************
10682  _spoolss_5c
10683 ****************************************************************/
10684
10685 WERROR _spoolss_5c(struct pipes_struct *p,
10686                    struct spoolss_5c *r)
10687 {
10688         p->rng_fault_state = true;
10689         return WERR_NOT_SUPPORTED;
10690 }
10691
10692 /****************************************************************
10693  _spoolss_5d
10694 ****************************************************************/
10695
10696 WERROR _spoolss_5d(struct pipes_struct *p,
10697                    struct spoolss_5d *r)
10698 {
10699         p->rng_fault_state = true;
10700         return WERR_NOT_SUPPORTED;
10701 }
10702
10703 /****************************************************************
10704  _spoolss_5e
10705 ****************************************************************/
10706
10707 WERROR _spoolss_5e(struct pipes_struct *p,
10708                    struct spoolss_5e *r)
10709 {
10710         p->rng_fault_state = true;
10711         return WERR_NOT_SUPPORTED;
10712 }
10713
10714 /****************************************************************
10715  _spoolss_5f
10716 ****************************************************************/
10717
10718 WERROR _spoolss_5f(struct pipes_struct *p,
10719                    struct spoolss_5f *r)
10720 {
10721         p->rng_fault_state = true;
10722         return WERR_NOT_SUPPORTED;
10723 }
10724
10725 /****************************************************************
10726  _spoolss_60
10727 ****************************************************************/
10728
10729 WERROR _spoolss_60(struct pipes_struct *p,
10730                    struct spoolss_60 *r)
10731 {
10732         p->rng_fault_state = true;
10733         return WERR_NOT_SUPPORTED;
10734 }
10735
10736 /****************************************************************
10737  _spoolss_61
10738 ****************************************************************/
10739
10740 WERROR _spoolss_61(struct pipes_struct *p,
10741                    struct spoolss_61 *r)
10742 {
10743         p->rng_fault_state = true;
10744         return WERR_NOT_SUPPORTED;
10745 }
10746
10747 /****************************************************************
10748  _spoolss_62
10749 ****************************************************************/
10750
10751 WERROR _spoolss_62(struct pipes_struct *p,
10752                    struct spoolss_62 *r)
10753 {
10754         p->rng_fault_state = true;
10755         return WERR_NOT_SUPPORTED;
10756 }
10757
10758 /****************************************************************
10759  _spoolss_63
10760 ****************************************************************/
10761
10762 WERROR _spoolss_63(struct pipes_struct *p,
10763                    struct spoolss_63 *r)
10764 {
10765         p->rng_fault_state = true;
10766         return WERR_NOT_SUPPORTED;
10767 }
10768
10769 /****************************************************************
10770  _spoolss_64
10771 ****************************************************************/
10772
10773 WERROR _spoolss_64(struct pipes_struct *p,
10774                    struct spoolss_64 *r)
10775 {
10776         p->rng_fault_state = true;
10777         return WERR_NOT_SUPPORTED;
10778 }
10779
10780 /****************************************************************
10781  _spoolss_65
10782 ****************************************************************/
10783
10784 WERROR _spoolss_65(struct pipes_struct *p,
10785                    struct spoolss_65 *r)
10786 {
10787         p->rng_fault_state = true;
10788         return WERR_NOT_SUPPORTED;
10789 }
10790
10791 /****************************************************************
10792  _spoolss_GetCorePrinterDrivers
10793 ****************************************************************/
10794
10795 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
10796                                       struct spoolss_GetCorePrinterDrivers *r)
10797 {
10798         p->rng_fault_state = true;
10799         return WERR_NOT_SUPPORTED;
10800 }
10801
10802 /****************************************************************
10803  _spoolss_67
10804 ****************************************************************/
10805
10806 WERROR _spoolss_67(struct pipes_struct *p,
10807                    struct spoolss_67 *r)
10808 {
10809         p->rng_fault_state = true;
10810         return WERR_NOT_SUPPORTED;
10811 }
10812
10813 /****************************************************************
10814  _spoolss_GetPrinterDriverPackagePath
10815 ****************************************************************/
10816
10817 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
10818                                             struct spoolss_GetPrinterDriverPackagePath *r)
10819 {
10820         p->rng_fault_state = true;
10821         return WERR_NOT_SUPPORTED;
10822 }
10823
10824 /****************************************************************
10825  _spoolss_69
10826 ****************************************************************/
10827
10828 WERROR _spoolss_69(struct pipes_struct *p,
10829                    struct spoolss_69 *r)
10830 {
10831         p->rng_fault_state = true;
10832         return WERR_NOT_SUPPORTED;
10833 }
10834
10835 /****************************************************************
10836  _spoolss_6a
10837 ****************************************************************/
10838
10839 WERROR _spoolss_6a(struct pipes_struct *p,
10840                    struct spoolss_6a *r)
10841 {
10842         p->rng_fault_state = true;
10843         return WERR_NOT_SUPPORTED;
10844 }
10845
10846 /****************************************************************
10847  _spoolss_6b
10848 ****************************************************************/
10849
10850 WERROR _spoolss_6b(struct pipes_struct *p,
10851                    struct spoolss_6b *r)
10852 {
10853         p->rng_fault_state = true;
10854         return WERR_NOT_SUPPORTED;
10855 }
10856
10857 /****************************************************************
10858  _spoolss_6c
10859 ****************************************************************/
10860
10861 WERROR _spoolss_6c(struct pipes_struct *p,
10862                    struct spoolss_6c *r)
10863 {
10864         p->rng_fault_state = true;
10865         return WERR_NOT_SUPPORTED;
10866 }
10867
10868 /****************************************************************
10869  _spoolss_6d
10870 ****************************************************************/
10871
10872 WERROR _spoolss_6d(struct pipes_struct *p,
10873                    struct spoolss_6d *r)
10874 {
10875         p->rng_fault_state = true;
10876         return WERR_NOT_SUPPORTED;
10877 }