s3: Fix Coverity ID 2195: NO_EFFECT
[samba.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 "nt_printing.h"
32 #include "srv_spoolss_util.h"
33 #include "../librpc/gen_ndr/srv_spoolss.h"
34 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
35 #include "rpc_client/init_spoolss.h"
36 #include "rpc_client/cli_pipe.h"
37 #include "librpc/gen_ndr/messaging.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
49 /* macros stolen from s4 spoolss server */
50 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
51         ((info)?ndr_size_##fn(info, level, 0):0)
52
53 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
54         ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
55
56 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
57         ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
58
59 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
60
61 #undef DBGC_CLASS
62 #define DBGC_CLASS DBGC_RPC_SRV
63
64 #ifndef MAX_OPEN_PRINTER_EXS
65 #define MAX_OPEN_PRINTER_EXS 50
66 #endif
67
68 struct notify_back_channel;
69
70 /* structure to store the printer handles */
71 /* and a reference to what it's pointing to */
72 /* and the notify info asked about */
73 /* that's the central struct */
74 struct printer_handle {
75         struct printer_handle *prev, *next;
76         bool document_started;
77         bool page_started;
78         uint32 jobid; /* jobid in printing backend */
79         int printer_type;
80         const char *servername;
81         fstring sharename;
82         uint32 type;
83         uint32 access_granted;
84         struct {
85                 uint32 flags;
86                 uint32 options;
87                 fstring localmachine;
88                 uint32 printerlocal;
89                 struct spoolss_NotifyOption *option;
90                 struct policy_handle cli_hnd;
91                 struct notify_back_channel *cli_chan;
92                 uint32 change;
93                 /* are we in a FindNextPrinterChangeNotify() call? */
94                 bool fnpcn;
95                 struct messaging_context *msg_ctx;
96         } notify;
97         struct {
98                 fstring machine;
99                 fstring user;
100         } client;
101
102         /* devmode sent in the OpenPrinter() call */
103         struct spoolss_DeviceMode *devmode;
104
105         /* TODO cache the printer info2 structure */
106         struct spoolss_PrinterInfo2 *info2;
107
108 };
109
110 static struct printer_handle *printers_list;
111
112 struct printer_session_counter {
113         struct printer_session_counter *next;
114         struct printer_session_counter *prev;
115
116         int snum;
117         uint32_t counter;
118 };
119
120 static struct printer_session_counter *counter_list;
121
122 struct notify_back_channel {
123         struct notify_back_channel *prev, *next;
124
125         /* associated client */
126         struct sockaddr_storage client_address;
127
128         /* print notify back-channel pipe handle*/
129         struct rpc_pipe_client *cli_pipe;
130         struct dcerpc_binding_handle *binding_handle;
131         uint32_t active_connections;
132 };
133
134 static struct notify_back_channel *back_channels;
135
136 /* Map generic permissions to printer object specific permissions */
137
138 const struct standard_mapping printer_std_mapping = {
139         PRINTER_READ,
140         PRINTER_WRITE,
141         PRINTER_EXECUTE,
142         PRINTER_ALL_ACCESS
143 };
144
145 /* Map generic permissions to print server object specific permissions */
146
147 const struct standard_mapping printserver_std_mapping = {
148         SERVER_READ,
149         SERVER_WRITE,
150         SERVER_EXECUTE,
151         SERVER_ALL_ACCESS
152 };
153
154 /* API table for Xcv Monitor functions */
155
156 struct xcv_api_table {
157         const char *name;
158         WERROR(*fn) (TALLOC_CTX *mem_ctx, struct security_token *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
159 };
160
161 static void prune_printername_cache(void);
162
163 /********************************************************************
164  * Canonicalize servername.
165  ********************************************************************/
166
167 static const char *canon_servername(const char *servername)
168 {
169         const char *pservername = servername;
170         while (*pservername == '\\') {
171                 pservername++;
172         }
173         return pservername;
174 }
175
176 /* translate between internal status numbers and NT status numbers */
177 static int nt_printj_status(int v)
178 {
179         switch (v) {
180         case LPQ_QUEUED:
181                 return 0;
182         case LPQ_PAUSED:
183                 return JOB_STATUS_PAUSED;
184         case LPQ_SPOOLING:
185                 return JOB_STATUS_SPOOLING;
186         case LPQ_PRINTING:
187                 return JOB_STATUS_PRINTING;
188         case LPQ_ERROR:
189                 return JOB_STATUS_ERROR;
190         case LPQ_DELETING:
191                 return JOB_STATUS_DELETING;
192         case LPQ_OFFLINE:
193                 return JOB_STATUS_OFFLINE;
194         case LPQ_PAPEROUT:
195                 return JOB_STATUS_PAPEROUT;
196         case LPQ_PRINTED:
197                 return JOB_STATUS_PRINTED;
198         case LPQ_DELETED:
199                 return JOB_STATUS_DELETED;
200         case LPQ_BLOCKED:
201                 return JOB_STATUS_BLOCKED_DEVQ;
202         case LPQ_USER_INTERVENTION:
203                 return JOB_STATUS_USER_INTERVENTION;
204         }
205         return 0;
206 }
207
208 static int nt_printq_status(int v)
209 {
210         switch (v) {
211         case LPQ_PAUSED:
212                 return PRINTER_STATUS_PAUSED;
213         case LPQ_QUEUED:
214         case LPQ_SPOOLING:
215         case LPQ_PRINTING:
216                 return 0;
217         }
218         return 0;
219 }
220
221 /***************************************************************************
222  Disconnect from the client
223 ****************************************************************************/
224
225 static void srv_spoolss_replycloseprinter(int snum,
226                                           struct printer_handle *prn_hnd)
227 {
228         WERROR result;
229         NTSTATUS status;
230
231         /*
232          * Tell the specific printing tdb we no longer want messages for this printer
233          * by deregistering our PID.
234          */
235
236         if (!print_notify_deregister_pid(snum)) {
237                 DEBUG(0, ("Failed to register our pid for printer %s\n",
238                           lp_const_servicename(snum)));
239         }
240
241         /* weird if the test succeeds !!! */
242         if (prn_hnd->notify.cli_chan == NULL ||
243             prn_hnd->notify.cli_chan->active_connections == 0) {
244                 DEBUG(0, ("Trying to close unexisting backchannel!\n"));
245                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
246                 TALLOC_FREE(prn_hnd->notify.cli_chan);
247                 return;
248         }
249
250         status = dcerpc_spoolss_ReplyClosePrinter(
251                                         prn_hnd->notify.cli_chan->binding_handle,
252                                         talloc_tos(),
253                                         &prn_hnd->notify.cli_hnd,
254                                         &result);
255         if (!NT_STATUS_IS_OK(status)) {
256                 DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
257                           nt_errstr(status)));
258                 result = ntstatus_to_werror(status);
259         } else if (!W_ERROR_IS_OK(result)) {
260                 DEBUG(0, ("reply_close_printer failed [%s].\n",
261                           win_errstr(result)));
262         }
263
264         /* if it's the last connection, deconnect the IPC$ share */
265         if (prn_hnd->notify.cli_chan->active_connections == 1) {
266
267                 prn_hnd->notify.cli_chan->binding_handle = NULL;
268                 cli_shutdown(rpc_pipe_np_smb_conn(prn_hnd->notify.cli_chan->cli_pipe));
269                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
270                 TALLOC_FREE(prn_hnd->notify.cli_chan);
271
272                 if (prn_hnd->notify.msg_ctx != NULL) {
273                         messaging_deregister(prn_hnd->notify.msg_ctx,
274                                              MSG_PRINTER_NOTIFY2, NULL);
275
276                         /*
277                          * Tell the serverid.tdb we're no longer
278                          * interested in printer notify messages.
279                          */
280
281                         serverid_register_msg_flags(
282                                 messaging_server_id(prn_hnd->notify.msg_ctx),
283                                 false, FLAG_MSG_PRINT_NOTIFY);
284                 }
285         }
286
287         if (prn_hnd->notify.cli_chan) {
288                 prn_hnd->notify.cli_chan->active_connections--;
289         }
290 }
291
292 /****************************************************************************
293  Functions to free a printer entry datastruct.
294 ****************************************************************************/
295
296 static int printer_entry_destructor(struct printer_handle *Printer)
297 {
298         if (Printer->notify.cli_chan != NULL &&
299             Printer->notify.cli_chan->active_connections > 0) {
300                 int snum = -1;
301
302                 switch(Printer->printer_type) {
303                 case SPLHND_SERVER:
304                         srv_spoolss_replycloseprinter(snum, Printer);
305                         break;
306
307                 case SPLHND_PRINTER:
308                         snum = print_queue_snum(Printer->sharename);
309                         if (snum != -1) {
310                                 srv_spoolss_replycloseprinter(snum, Printer);
311                         }
312                         break;
313                 default:
314                         break;
315                 }
316         }
317
318         Printer->notify.flags=0;
319         Printer->notify.options=0;
320         Printer->notify.localmachine[0]='\0';
321         Printer->notify.printerlocal=0;
322         TALLOC_FREE(Printer->notify.option);
323         TALLOC_FREE(Printer->devmode);
324
325         /* Remove from the internal list. */
326         DLIST_REMOVE(printers_list, Printer);
327         return 0;
328 }
329
330 /****************************************************************************
331   find printer index by handle
332 ****************************************************************************/
333
334 static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
335                                                         struct policy_handle *hnd)
336 {
337         struct printer_handle *find_printer = NULL;
338
339         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
340                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
341                 return NULL;
342         }
343
344         return find_printer;
345 }
346
347 /****************************************************************************
348  Close printer index by handle.
349 ****************************************************************************/
350
351 static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
352 {
353         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
354
355         if (!Printer) {
356                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
357                         OUR_HANDLE(hnd)));
358                 return false;
359         }
360
361         close_policy_hnd(p, hnd);
362
363         return true;
364 }
365
366 /****************************************************************************
367  Delete a printer given a handle.
368 ****************************************************************************/
369
370 static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
371                                   const char *sharename,
372                                   struct messaging_context *msg_ctx)
373 {
374         char *cmd = lp_deleteprinter_cmd();
375         char *command = NULL;
376         int ret;
377         bool is_print_op = false;
378
379         /* can't fail if we don't try */
380
381         if ( !*cmd )
382                 return WERR_OK;
383
384         command = talloc_asprintf(ctx,
385                         "%s \"%s\"",
386                         cmd, sharename);
387         if (!command) {
388                 return WERR_NOMEM;
389         }
390         if ( token )
391                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
392
393         DEBUG(10,("Running [%s]\n", command));
394
395         /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
396
397         if ( is_print_op )
398                 become_root();
399
400         if ( (ret = smbrun(command, NULL)) == 0 ) {
401                 /* Tell everyone we updated smb.conf. */
402                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
403         }
404
405         if ( is_print_op )
406                 unbecome_root();
407
408         /********** END SePrintOperatorPrivlege BLOCK **********/
409
410         DEBUGADD(10,("returned [%d]\n", ret));
411
412         TALLOC_FREE(command);
413
414         if (ret != 0)
415                 return WERR_BADFID; /* What to return here? */
416
417         /* go ahead and re-read the services immediately */
418         become_root();
419         reload_services(msg_ctx, -1, false);
420         unbecome_root();
421
422         if ( lp_servicenumber( sharename ) >= 0 )
423                 return WERR_ACCESS_DENIED;
424
425         return WERR_OK;
426 }
427
428 /****************************************************************************
429  Delete a printer given a handle.
430 ****************************************************************************/
431
432 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
433 {
434         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
435         WERROR result;
436
437         if (!Printer) {
438                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
439                         OUR_HANDLE(hnd)));
440                 return WERR_BADFID;
441         }
442
443         /*
444          * It turns out that Windows allows delete printer on a handle
445          * opened by an admin user, then used on a pipe handle created
446          * by an anonymous user..... but they're working on security.... riiight !
447          * JRA.
448          */
449
450         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
451                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
452                 return WERR_ACCESS_DENIED;
453         }
454
455         /* this does not need a become root since the access check has been
456            done on the handle already */
457
458         result = winreg_delete_printer_key(p->mem_ctx,
459                                            get_session_info_system(),
460                                            p->msg_ctx,
461                                            Printer->sharename,
462                                            "");
463         if (!W_ERROR_IS_OK(result)) {
464                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
465                 return WERR_BADFID;
466         }
467
468         result = delete_printer_hook(p->mem_ctx, p->session_info->security_token,
469                                      Printer->sharename, p->msg_ctx);
470         if (!W_ERROR_IS_OK(result)) {
471                 return result;
472         }
473         prune_printername_cache();
474         return WERR_OK;
475 }
476
477 /****************************************************************************
478  Return the snum of a printer corresponding to an handle.
479 ****************************************************************************/
480
481 static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
482                              int *number, struct share_params **params)
483 {
484         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
485
486         if (!Printer) {
487                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
488                         OUR_HANDLE(hnd)));
489                 return false;
490         }
491
492         switch (Printer->printer_type) {
493                 case SPLHND_PRINTER:
494                         DEBUG(4,("short name:%s\n", Printer->sharename));
495                         *number = print_queue_snum(Printer->sharename);
496                         return (*number != -1);
497                 case SPLHND_SERVER:
498                         return false;
499                 default:
500                         return false;
501         }
502 }
503
504 /****************************************************************************
505  Set printer handle type.
506  Check if it's \\server or \\server\printer
507 ****************************************************************************/
508
509 static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
510 {
511         DEBUG(3,("Setting printer type=%s\n", handlename));
512
513         /* it's a print server */
514         if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
515                 DEBUGADD(4,("Printer is a print server\n"));
516                 Printer->printer_type = SPLHND_SERVER;
517         }
518         /* it's a printer (set_printer_hnd_name() will handle port monitors */
519         else {
520                 DEBUGADD(4,("Printer is a printer\n"));
521                 Printer->printer_type = SPLHND_PRINTER;
522         }
523
524         return true;
525 }
526
527 static void prune_printername_cache_fn(const char *key, const char *value,
528                                        time_t timeout, void *private_data)
529 {
530         gencache_del(key);
531 }
532
533 static void prune_printername_cache(void)
534 {
535         gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
536 }
537
538 /****************************************************************************
539  Set printer handle name..  Accept names like \\server, \\server\printer,
540  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
541  the MSDN docs regarding OpenPrinter() for details on the XcvData() and
542  XcvDataPort() interface.
543 ****************************************************************************/
544
545 static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
546                                    const struct auth_serversupplied_info *session_info,
547                                    struct messaging_context *msg_ctx,
548                                    struct printer_handle *Printer,
549                                    const char *handlename)
550 {
551         int snum;
552         int n_services=lp_numservices();
553         char *aprinter;
554         const char *printername;
555         const char *servername = NULL;
556         fstring sname;
557         bool found = false;
558         struct spoolss_PrinterInfo2 *info2 = NULL;
559         WERROR result;
560         char *p;
561
562         /*
563          * Hopefully nobody names his printers like this. Maybe \ or ,
564          * are illegal in printer names even?
565          */
566         const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
567         char *cache_key;
568         char *tmp;
569
570         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
571                 (unsigned long)strlen(handlename)));
572
573         aprinter = CONST_DISCARD(char *, handlename);
574         if ( *handlename == '\\' ) {
575                 servername = canon_servername(handlename);
576                 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
577                         *aprinter = '\0';
578                         aprinter++;
579                 }
580                 if (!is_myname_or_ipaddr(servername)) {
581                         return WERR_INVALID_PRINTER_NAME;
582                 }
583                 Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
584                 if (Printer->servername == NULL) {
585                         return WERR_NOMEM;
586                 }
587         }
588
589         if (Printer->printer_type == SPLHND_SERVER) {
590                 return WERR_OK;
591         }
592
593         if (Printer->printer_type != SPLHND_PRINTER) {
594                 return WERR_INVALID_HANDLE;
595         }
596
597         DEBUGADD(5, ("searching for [%s]\n", aprinter));
598
599         p = strchr(aprinter, ',');
600         if (p != NULL) {
601                 char *p2 = p;
602                 p++;
603                 if (*p == ' ') {
604                         p++;
605                 }
606                 if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
607                         *p2 = '\0';
608                 } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
609                         *p2 = '\0';
610                 }
611         }
612
613         if (p) {
614                 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
615         }
616
617         /* check for the Port Monitor Interface */
618         if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
619                 Printer->printer_type = SPLHND_PORTMON_TCP;
620                 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
621                 found = true;
622         }
623         else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
624                 Printer->printer_type = SPLHND_PORTMON_LOCAL;
625                 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
626                 found = true;
627         }
628
629         /*
630          * With hundreds of printers, the "for" loop iterating all
631          * shares can be quite expensive, as it is done on every
632          * OpenPrinter. The loop maps "aprinter" to "sname", the
633          * result of which we cache in gencache.
634          */
635
636         cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s",
637                                     aprinter);
638         if ((cache_key != NULL) && gencache_get(cache_key, &tmp, NULL)) {
639
640                 found = (strcmp(tmp, printer_not_found) != 0);
641                 if (!found) {
642                         DEBUG(4, ("Printer %s not found\n", aprinter));
643                         SAFE_FREE(tmp);
644                         return WERR_INVALID_PRINTER_NAME;
645                 }
646                 fstrcpy(sname, tmp);
647                 SAFE_FREE(tmp);
648         }
649
650         /* Search all sharenames first as this is easier than pulling
651            the printer_info_2 off of disk. Don't use find_service() since
652            that calls out to map_username() */
653
654         /* do another loop to look for printernames */
655         for (snum = 0; !found && snum < n_services; snum++) {
656                 const char *printer = lp_const_servicename(snum);
657
658                 /* no point going on if this is not a printer */
659                 if (!(lp_snum_ok(snum) && lp_print_ok(snum))) {
660                         continue;
661                 }
662
663                 /* ignore [printers] share */
664                 if (strequal(printer, "printers")) {
665                         continue;
666                 }
667
668                 fstrcpy(sname, printer);
669                 if (strequal(aprinter, printer)) {
670                         found = true;
671                         break;
672                 }
673
674                 /* no point looking up the printer object if
675                    we aren't allowing printername != sharename */
676                 if (lp_force_printername(snum)) {
677                         continue;
678                 }
679
680                 result = winreg_get_printer(mem_ctx,
681                                             session_info,
682                                             msg_ctx,
683                                             sname,
684                                             &info2);
685                 if ( !W_ERROR_IS_OK(result) ) {
686                         DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
687                                  sname, win_errstr(result)));
688                         continue;
689                 }
690
691                 printername = strrchr(info2->printername, '\\');
692                 if (printername == NULL) {
693                         printername = info2->printername;
694                 } else {
695                         printername++;
696                 }
697
698                 if (strequal(printername, aprinter)) {
699                         found = true;
700                         break;
701                 }
702
703                 DEBUGADD(10, ("printername: %s\n", printername));
704
705                 TALLOC_FREE(info2);
706         }
707
708         if ( !found ) {
709                 if (cache_key != NULL) {
710                         gencache_set(cache_key, printer_not_found,
711                                      time(NULL)+300);
712                         TALLOC_FREE(cache_key);
713                 }
714                 DEBUGADD(4,("Printer not found\n"));
715                 return WERR_INVALID_PRINTER_NAME;
716         }
717
718         if (cache_key != NULL) {
719                 gencache_set(cache_key, sname, time(NULL)+300);
720                 TALLOC_FREE(cache_key);
721         }
722
723         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
724
725         fstrcpy(Printer->sharename, sname);
726
727         return WERR_OK;
728 }
729
730 /****************************************************************************
731  Find first available printer slot. creates a printer handle for you.
732  ****************************************************************************/
733
734 static WERROR open_printer_hnd(struct pipes_struct *p,
735                                struct policy_handle *hnd,
736                                const char *name,
737                                uint32_t access_granted)
738 {
739         struct printer_handle *new_printer;
740         WERROR result;
741
742         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
743
744         new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
745         if (new_printer == NULL) {
746                 return WERR_NOMEM;
747         }
748         talloc_set_destructor(new_printer, printer_entry_destructor);
749
750         /* This also steals the printer_handle on the policy_handle */
751         if (!create_policy_hnd(p, hnd, new_printer)) {
752                 TALLOC_FREE(new_printer);
753                 return WERR_INVALID_HANDLE;
754         }
755
756         /* Add to the internal list. */
757         DLIST_ADD(printers_list, new_printer);
758
759         new_printer->notify.option=NULL;
760
761         if (!set_printer_hnd_printertype(new_printer, name)) {
762                 close_printer_handle(p, hnd);
763                 return WERR_INVALID_HANDLE;
764         }
765
766         result = set_printer_hnd_name(p->mem_ctx,
767                                       get_session_info_system(),
768                                       p->msg_ctx,
769                                       new_printer, name);
770         if (!W_ERROR_IS_OK(result)) {
771                 close_printer_handle(p, hnd);
772                 return result;
773         }
774
775         new_printer->access_granted = access_granted;
776
777         DEBUG(5, ("%d printer handles active\n",
778                   (int)num_pipe_handles(p)));
779
780         return WERR_OK;
781 }
782
783 /***************************************************************************
784  check to see if the client motify handle is monitoring the notification
785  given by (notify_type, notify_field).
786  **************************************************************************/
787
788 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
789                                       uint16_t notify_field)
790 {
791         return true;
792 }
793
794 static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
795                                 uint16_t notify_field)
796 {
797         struct spoolss_NotifyOption *option = p->notify.option;
798         uint32_t i, j;
799
800         /*
801          * Flags should always be zero when the change notify
802          * is registered by the client's spooler.  A user Win32 app
803          * might use the flags though instead of the NOTIFY_OPTION_INFO
804          * --jerry
805          */
806
807         if (!option) {
808                 return false;
809         }
810
811         if (p->notify.flags)
812                 return is_monitoring_event_flags(
813                         p->notify.flags, notify_type, notify_field);
814
815         for (i = 0; i < option->count; i++) {
816
817                 /* Check match for notify_type */
818
819                 if (option->types[i].type != notify_type)
820                         continue;
821
822                 /* Check match for field */
823
824                 for (j = 0; j < option->types[i].count; j++) {
825                         if (option->types[i].fields[j].field == notify_field) {
826                                 return true;
827                         }
828                 }
829         }
830
831         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
832                    p->servername, p->sharename, notify_type, notify_field));
833
834         return false;
835 }
836
837 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
838         _data->data.integer[0] = _integer; \
839         _data->data.integer[1] = 0;
840
841
842 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
843         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
844         if (!_data->data.string.string) {\
845                 _data->data.string.size = 0; \
846         } \
847         _data->data.string.size = strlen_m_term(_p) * 2;
848
849 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
850         _data->data.devmode.devmode = _devmode;
851
852 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
853         _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
854         if (!_data->data.sd.sd) { \
855                 _data->data.sd.sd_size = 0; \
856         } \
857         _data->data.sd.sd_size = \
858                 ndr_size_security_descriptor(_data->data.sd.sd, 0);
859
860 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
861                                    struct tm *t,
862                                    const char **pp,
863                                    uint32_t *plen)
864 {
865         struct spoolss_Time st;
866         uint32_t len = 16;
867         char *p;
868
869         if (!init_systemtime(&st, t)) {
870                 return;
871         }
872
873         p = talloc_array(mem_ctx, char, len);
874         if (!p) {
875                 return;
876         }
877
878         /*
879          * Systemtime must be linearized as a set of UINT16's.
880          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
881          */
882
883         SSVAL(p, 0, st.year);
884         SSVAL(p, 2, st.month);
885         SSVAL(p, 4, st.day_of_week);
886         SSVAL(p, 6, st.day);
887         SSVAL(p, 8, st.hour);
888         SSVAL(p, 10, st.minute);
889         SSVAL(p, 12, st.second);
890         SSVAL(p, 14, st.millisecond);
891
892         *pp = p;
893         *plen = len;
894 }
895
896 /* Convert a notification message to a struct spoolss_Notify */
897
898 static void notify_one_value(struct spoolss_notify_msg *msg,
899                              struct spoolss_Notify *data,
900                              TALLOC_CTX *mem_ctx)
901 {
902         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
903 }
904
905 static void notify_string(struct spoolss_notify_msg *msg,
906                           struct spoolss_Notify *data,
907                           TALLOC_CTX *mem_ctx)
908 {
909         /* The length of the message includes the trailing \0 */
910
911         data->data.string.size = msg->len * 2;
912         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
913         if (!data->data.string.string) {
914                 data->data.string.size = 0;
915                 return;
916         }
917 }
918
919 static void notify_system_time(struct spoolss_notify_msg *msg,
920                                struct spoolss_Notify *data,
921                                TALLOC_CTX *mem_ctx)
922 {
923         data->data.string.string = NULL;
924         data->data.string.size = 0;
925
926         if (msg->len != sizeof(time_t)) {
927                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
928                           msg->len));
929                 return;
930         }
931
932         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
933                                &data->data.string.string,
934                                &data->data.string.size);
935 }
936
937 struct notify2_message_table {
938         const char *name;
939         void (*fn)(struct spoolss_notify_msg *msg,
940                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
941 };
942
943 static struct notify2_message_table printer_notify_table[] = {
944         /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
945         /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
946         /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
947         /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
948         /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
949         /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
950         /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
951         /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
952         /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
953         /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
954         /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
955         /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
956         /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
957         /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
958         /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
959         /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
960         /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
961         /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
962         /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
963 };
964
965 static struct notify2_message_table job_notify_table[] = {
966         /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
967         /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
968         /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
969         /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
970         /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
971         /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
972         /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
973         /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
974         /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
975         /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
976         /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
977         /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
978         /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
979         /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
980         /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
981         /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
982         /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
983         /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
984         /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
985         /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
986         /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
987         /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
988         /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
989         /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
990 };
991
992
993 /***********************************************************************
994  Allocate talloc context for container object
995  **********************************************************************/
996
997 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
998 {
999         if ( !ctr )
1000                 return;
1001
1002         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
1003
1004         return;
1005 }
1006
1007 /***********************************************************************
1008  release all allocated memory and zero out structure
1009  **********************************************************************/
1010
1011 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1012 {
1013         if ( !ctr )
1014                 return;
1015
1016         if ( ctr->ctx )
1017                 talloc_destroy(ctr->ctx);
1018
1019         ZERO_STRUCTP(ctr);
1020
1021         return;
1022 }
1023
1024 /***********************************************************************
1025  **********************************************************************/
1026
1027 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1028 {
1029         if ( !ctr )
1030                 return NULL;
1031
1032         return ctr->ctx;
1033 }
1034
1035 /***********************************************************************
1036  **********************************************************************/
1037
1038 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1039 {
1040         if ( !ctr || !ctr->msg_groups )
1041                 return NULL;
1042
1043         if ( idx >= ctr->num_groups )
1044                 return NULL;
1045
1046         return &ctr->msg_groups[idx];
1047
1048 }
1049
1050 /***********************************************************************
1051  How many groups of change messages do we have ?
1052  **********************************************************************/
1053
1054 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1055 {
1056         if ( !ctr )
1057                 return 0;
1058
1059         return ctr->num_groups;
1060 }
1061
1062 /***********************************************************************
1063  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1064  **********************************************************************/
1065
1066 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1067 {
1068         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
1069         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
1070         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
1071         int                             i, new_slot;
1072
1073         if ( !ctr || !msg )
1074                 return 0;
1075
1076         /* loop over all groups looking for a matching printer name */
1077
1078         for ( i=0; i<ctr->num_groups; i++ ) {
1079                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1080                         break;
1081         }
1082
1083         /* add a new group? */
1084
1085         if ( i == ctr->num_groups ) {
1086                 ctr->num_groups++;
1087
1088                 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1089                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1090                         return 0;
1091                 }
1092                 ctr->msg_groups = groups;
1093
1094                 /* clear the new entry and set the printer name */
1095
1096                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1097                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1098         }
1099
1100         /* add the change messages; 'i' is the correct index now regardless */
1101
1102         msg_grp = &ctr->msg_groups[i];
1103
1104         msg_grp->num_msgs++;
1105
1106         if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1107                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1108                 return 0;
1109         }
1110         msg_grp->msgs = msg_list;
1111
1112         new_slot = msg_grp->num_msgs-1;
1113         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1114
1115         /* need to allocate own copy of data */
1116
1117         if ( msg->len != 0 )
1118                 msg_grp->msgs[new_slot].notify.data = (char *)
1119                         TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
1120
1121         return ctr->num_groups;
1122 }
1123
1124 static void construct_info_data(struct spoolss_Notify *info_data,
1125                                 enum spoolss_NotifyType type,
1126                                 uint16_t field, int id);
1127
1128 /***********************************************************************
1129  Send a change notication message on all handles which have a call
1130  back registered
1131  **********************************************************************/
1132
1133 static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1134                                   struct printer_handle *prn_hnd,
1135                                   SPOOLSS_NOTIFY_MSG *messages,
1136                                   uint32_t num_msgs,
1137                                   struct spoolss_Notify **_notifies,
1138                                   int *_count)
1139 {
1140         struct spoolss_Notify *notifies;
1141         SPOOLSS_NOTIFY_MSG *msg;
1142         int count = 0;
1143         uint32_t id;
1144         int i;
1145
1146         notifies = talloc_zero_array(mem_ctx,
1147                                      struct spoolss_Notify, num_msgs);
1148         if (!notifies) {
1149                 return ENOMEM;
1150         }
1151
1152         for (i = 0; i < num_msgs; i++) {
1153
1154                 msg = &messages[i];
1155
1156                 /* Are we monitoring this event? */
1157
1158                 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1159                         continue;
1160                 }
1161
1162                 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1163                            "for printer [%s]\n",
1164                            msg->type, msg->field, prn_hnd->sharename));
1165
1166                 /*
1167                  * if the is a printer notification handle and not a job
1168                  * notification type, then set the id to 0.
1169                  * Otherwise just use what was specified in the message.
1170                  *
1171                  * When registering change notification on a print server
1172                  * handle we always need to send back the id (snum) matching
1173                  * the printer for which the change took place.
1174                  * For change notify registered on a printer handle,
1175                  * this does not matter and the id should be 0.
1176                  *
1177                  * --jerry
1178                  */
1179
1180                 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1181                     (prn_hnd->printer_type == SPLHND_PRINTER)) {
1182                         id = 0;
1183                 } else {
1184                         id = msg->id;
1185                 }
1186
1187                 /* Convert unix jobid to smb jobid */
1188
1189                 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1190                         id = sysjob_to_jobid(msg->id);
1191
1192                         if (id == -1) {
1193                                 DEBUG(3, ("no such unix jobid %d\n",
1194                                           msg->id));
1195                                 continue;
1196                         }
1197                 }
1198
1199                 construct_info_data(&notifies[count],
1200                                     msg->type, msg->field, id);
1201
1202                 switch(msg->type) {
1203                 case PRINTER_NOTIFY_TYPE:
1204                         if (printer_notify_table[msg->field].fn) {
1205                                 printer_notify_table[msg->field].fn(msg,
1206                                                 &notifies[count], mem_ctx);
1207                         }
1208                         break;
1209
1210                 case JOB_NOTIFY_TYPE:
1211                         if (job_notify_table[msg->field].fn) {
1212                                 job_notify_table[msg->field].fn(msg,
1213                                                 &notifies[count], mem_ctx);
1214                         }
1215                         break;
1216
1217                 default:
1218                         DEBUG(5, ("Unknown notification type %d\n",
1219                                   msg->type));
1220                         continue;
1221                 }
1222
1223                 count++;
1224         }
1225
1226         *_notifies = notifies;
1227         *_count = count;
1228
1229         return 0;
1230 }
1231
1232 static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1233                                 struct printer_handle *prn_hnd,
1234                                 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1235 {
1236         struct spoolss_Notify *notifies;
1237         int count = 0;
1238         union spoolss_ReplyPrinterInfo info;
1239         struct spoolss_NotifyInfo info0;
1240         uint32_t reply_result;
1241         NTSTATUS status;
1242         WERROR werr;
1243         int ret;
1244
1245         /* Is there notification on this handle? */
1246         if (prn_hnd->notify.cli_chan == NULL ||
1247             prn_hnd->notify.cli_chan->active_connections == 0) {
1248                 return 0;
1249         }
1250
1251         DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1252                    prn_hnd->servername, prn_hnd->sharename));
1253
1254         /* For this printer? Print servers always receive notifications. */
1255         if ((prn_hnd->printer_type == SPLHND_PRINTER)  &&
1256             (!strequal(msg_group->printername, prn_hnd->sharename))) {
1257                 return 0;
1258         }
1259
1260         DEBUG(10,("Our printer\n"));
1261
1262         /* build the array of change notifications */
1263         ret = build_notify2_messages(mem_ctx, prn_hnd,
1264                                      msg_group->msgs,
1265                                      msg_group->num_msgs,
1266                                      &notifies, &count);
1267         if (ret) {
1268                 return ret;
1269         }
1270
1271         info0.version   = 0x2;
1272         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1273         info0.count     = count;
1274         info0.notifies  = notifies;
1275
1276         info.info0 = &info0;
1277
1278         status = dcerpc_spoolss_RouterReplyPrinterEx(
1279                                 prn_hnd->notify.cli_chan->binding_handle,
1280                                 mem_ctx,
1281                                 &prn_hnd->notify.cli_hnd,
1282                                 prn_hnd->notify.change, /* color */
1283                                 prn_hnd->notify.flags,
1284                                 &reply_result,
1285                                 0, /* reply_type, must be 0 */
1286                                 info, &werr);
1287         if (!NT_STATUS_IS_OK(status)) {
1288                 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1289                           "failed: %s\n",
1290                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1291                           nt_errstr(status)));
1292                 werr = ntstatus_to_werror(status);
1293         } else if (!W_ERROR_IS_OK(werr)) {
1294                 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1295                           "failed: %s\n",
1296                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1297                           win_errstr(werr)));
1298         }
1299         switch (reply_result) {
1300         case 0:
1301                 break;
1302         case PRINTER_NOTIFY_INFO_DISCARDED:
1303         case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1304         case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1305                 break;
1306         default:
1307                 break;
1308         }
1309
1310         return 0;
1311 }
1312
1313 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1314 {
1315         struct printer_handle    *p;
1316         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
1317         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1318         int ret;
1319
1320         if ( !msg_group ) {
1321                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1322                 return;
1323         }
1324
1325         if (!msg_group->msgs) {
1326                 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1327                 return;
1328         }
1329
1330         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1331
1332         /* loop over all printers */
1333
1334         for (p = printers_list; p; p = p->next) {
1335                 ret = send_notify2_printer(mem_ctx, p, msg_group);
1336                 if (ret) {
1337                         goto done;
1338                 }
1339         }
1340
1341 done:
1342         DEBUG(8,("send_notify2_changes: Exit...\n"));
1343         return;
1344 }
1345
1346 /***********************************************************************
1347  **********************************************************************/
1348
1349 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1350 {
1351
1352         uint32_t tv_sec, tv_usec;
1353         size_t offset = 0;
1354
1355         /* Unpack message */
1356
1357         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1358                              msg->printer);
1359
1360         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1361                                 &tv_sec, &tv_usec,
1362                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1363
1364         if (msg->len == 0)
1365                 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1366                            &msg->notify.value[0], &msg->notify.value[1]);
1367         else
1368                 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1369                            &msg->len, &msg->notify.data);
1370
1371         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1372                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1373
1374         tv->tv_sec = tv_sec;
1375         tv->tv_usec = tv_usec;
1376
1377         if (msg->len == 0)
1378                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1379                           msg->notify.value[1]));
1380         else
1381                 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1382
1383         return true;
1384 }
1385
1386 /********************************************************************
1387  Receive a notify2 message list
1388  ********************************************************************/
1389
1390 static void receive_notify2_message_list(struct messaging_context *msg,
1391                                          void *private_data,
1392                                          uint32_t msg_type,
1393                                          struct server_id server_id,
1394                                          DATA_BLOB *data)
1395 {
1396         size_t                  msg_count, i;
1397         char                    *buf = (char *)data->data;
1398         char                    *msg_ptr;
1399         size_t                  msg_len;
1400         SPOOLSS_NOTIFY_MSG      notify;
1401         SPOOLSS_NOTIFY_MSG_CTR  messages;
1402         int                     num_groups;
1403
1404         if (data->length < 4) {
1405                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1406                 return;
1407         }
1408
1409         msg_count = IVAL(buf, 0);
1410         msg_ptr = buf + 4;
1411
1412         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1413
1414         if (msg_count == 0) {
1415                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1416                 return;
1417         }
1418
1419         /* initialize the container */
1420
1421         ZERO_STRUCT( messages );
1422         notify_msg_ctr_init( &messages );
1423
1424         /*
1425          * build message groups for each printer identified
1426          * in a change_notify msg.  Remember that a PCN message
1427          * includes the handle returned for the srv_spoolss_replyopenprinter()
1428          * call.  Therefore messages are grouped according to printer handle.
1429          */
1430
1431         for ( i=0; i<msg_count; i++ ) {
1432                 struct timeval msg_tv;
1433
1434                 if (msg_ptr + 4 - buf > data->length) {
1435                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1436                         return;
1437                 }
1438
1439                 msg_len = IVAL(msg_ptr,0);
1440                 msg_ptr += 4;
1441
1442                 if (msg_ptr + msg_len - buf > data->length) {
1443                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1444                         return;
1445                 }
1446
1447                 /* unpack messages */
1448
1449                 ZERO_STRUCT( notify );
1450                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1451                 msg_ptr += msg_len;
1452
1453                 /* add to correct list in container */
1454
1455                 notify_msg_ctr_addmsg( &messages, &notify );
1456
1457                 /* free memory that might have been allocated by notify2_unpack_msg() */
1458
1459                 if ( notify.len != 0 )
1460                         SAFE_FREE( notify.notify.data );
1461         }
1462
1463         /* process each group of messages */
1464
1465         num_groups = notify_msg_ctr_numgroups( &messages );
1466         for ( i=0; i<num_groups; i++ )
1467                 send_notify2_changes( &messages, i );
1468
1469
1470         /* cleanup */
1471
1472         DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1473                 (uint32_t)msg_count ));
1474
1475         notify_msg_ctr_destroy( &messages );
1476
1477         return;
1478 }
1479
1480 /********************************************************************
1481  Send a message to ourself about new driver being installed
1482  so we can upgrade the information for each printer bound to this
1483  driver
1484  ********************************************************************/
1485
1486 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1487                                             struct messaging_context *msg_ctx)
1488 {
1489         int len = strlen(drivername);
1490
1491         if (!len)
1492                 return false;
1493
1494         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1495                 drivername));
1496
1497         messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1498                            MSG_PRINTER_DRVUPGRADE,
1499                            (uint8_t *)drivername, len+1);
1500
1501         return true;
1502 }
1503
1504 void srv_spoolss_cleanup(void)
1505 {
1506         struct printer_session_counter *session_counter;
1507
1508         for (session_counter = counter_list;
1509              session_counter != NULL;
1510              session_counter = counter_list) {
1511                 DLIST_REMOVE(counter_list, session_counter);
1512                 TALLOC_FREE(session_counter);
1513         }
1514 }
1515
1516 /**********************************************************************
1517  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1518  over all printers, upgrading ones as necessary
1519  **********************************************************************/
1520
1521 void do_drv_upgrade_printer(struct messaging_context *msg,
1522                             void *private_data,
1523                             uint32_t msg_type,
1524                             struct server_id server_id,
1525                             DATA_BLOB *data)
1526 {
1527         TALLOC_CTX *tmp_ctx;
1528         struct auth_serversupplied_info *session_info = NULL;
1529         struct spoolss_PrinterInfo2 *pinfo2;
1530         NTSTATUS status;
1531         WERROR result;
1532         const char *drivername;
1533         int snum;
1534         int n_services = lp_numservices();
1535
1536         tmp_ctx = talloc_new(NULL);
1537         if (!tmp_ctx) return;
1538
1539         status = make_session_info_system(tmp_ctx, &session_info);
1540         if (!NT_STATUS_IS_OK(status)) {
1541                 DEBUG(0, ("do_drv_upgrade_printer: "
1542                           "Could not create system session_info\n"));
1543                 goto done;
1544         }
1545
1546         drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1547         if (!drivername) {
1548                 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1549                 goto done;
1550         }
1551
1552         DEBUG(10, ("do_drv_upgrade_printer: "
1553                    "Got message for new driver [%s]\n", drivername));
1554
1555         /* Iterate the printer list */
1556
1557         for (snum = 0; snum < n_services; snum++) {
1558                 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1559                         continue;
1560                 }
1561
1562                 /* ignore [printers] share */
1563                 if (strequal(lp_const_servicename(snum), "printers")) {
1564                         continue;
1565                 }
1566
1567                 result = winreg_get_printer(tmp_ctx, session_info, msg,
1568                                             lp_const_servicename(snum),
1569                                             &pinfo2);
1570
1571                 if (!W_ERROR_IS_OK(result)) {
1572                         continue;
1573                 }
1574
1575                 if (!pinfo2->drivername) {
1576                         continue;
1577                 }
1578
1579                 if (strcmp(drivername, pinfo2->drivername) != 0) {
1580                         continue;
1581                 }
1582
1583                 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1584
1585                 /* all we care about currently is the change_id */
1586                 result = winreg_printer_update_changeid(tmp_ctx,
1587                                                         session_info,
1588                                                         msg,
1589                                                         pinfo2->printername);
1590
1591                 if (!W_ERROR_IS_OK(result)) {
1592                         DEBUG(3, ("do_drv_upgrade_printer: "
1593                                   "Failed to update changeid [%s]\n",
1594                                   win_errstr(result)));
1595                 }
1596         }
1597
1598         /* all done */
1599 done:
1600         talloc_free(tmp_ctx);
1601 }
1602
1603 /********************************************************************
1604  Update the cache for all printq's with a registered client
1605  connection
1606  ********************************************************************/
1607
1608 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1609 {
1610         struct printer_handle *printer = printers_list;
1611         int snum;
1612
1613         /* loop through all printers and update the cache where
1614            a client is connected */
1615         while (printer) {
1616                 if ((printer->printer_type == SPLHND_PRINTER) &&
1617                     ((printer->notify.cli_chan != NULL) &&
1618                      (printer->notify.cli_chan->active_connections > 0))) {
1619                         snum = print_queue_snum(printer->sharename);
1620                         print_queue_status(msg_ctx, snum, NULL, NULL);
1621                 }
1622
1623                 printer = printer->next;
1624         }
1625
1626         return;
1627 }
1628
1629 /****************************************************************
1630  _spoolss_OpenPrinter
1631 ****************************************************************/
1632
1633 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1634                             struct spoolss_OpenPrinter *r)
1635 {
1636         struct spoolss_OpenPrinterEx e;
1637         WERROR werr;
1638
1639         ZERO_STRUCT(e.in.userlevel);
1640
1641         e.in.printername        = r->in.printername;
1642         e.in.datatype           = r->in.datatype;
1643         e.in.devmode_ctr        = r->in.devmode_ctr;
1644         e.in.access_mask        = r->in.access_mask;
1645         e.in.level              = 0;
1646
1647         e.out.handle            = r->out.handle;
1648
1649         werr = _spoolss_OpenPrinterEx(p, &e);
1650
1651         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1652                 /* OpenPrinterEx returns this for a bad
1653                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1654                  * instead.
1655                  */
1656                 werr = WERR_INVALID_PRINTER_NAME;
1657         }
1658
1659         return werr;
1660 }
1661
1662 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1663                               struct spoolss_DeviceMode *orig,
1664                               struct spoolss_DeviceMode **dest)
1665 {
1666         struct spoolss_DeviceMode *dm;
1667
1668         dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1669         if (!dm) {
1670                 return WERR_NOMEM;
1671         }
1672
1673         /* copy all values, then duplicate strings and structs */
1674         *dm = *orig;
1675
1676         dm->devicename = talloc_strdup(dm, orig->devicename);
1677         if (!dm->devicename) {
1678                 return WERR_NOMEM;
1679         }
1680         dm->formname = talloc_strdup(dm, orig->formname);
1681         if (!dm->formname) {
1682                 return WERR_NOMEM;
1683         }
1684         if (orig->driverextra_data.data) {
1685                 dm->driverextra_data.data =
1686                         (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1687                                         orig->driverextra_data.length);
1688                 if (!dm->driverextra_data.data) {
1689                         return WERR_NOMEM;
1690                 }
1691         }
1692
1693         *dest = dm;
1694         return WERR_OK;
1695 }
1696
1697 /****************************************************************
1698  _spoolss_OpenPrinterEx
1699 ****************************************************************/
1700
1701 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1702                               struct spoolss_OpenPrinterEx *r)
1703 {
1704         int snum;
1705         struct printer_handle *Printer=NULL;
1706         WERROR result;
1707
1708         if (!r->in.printername) {
1709                 return WERR_INVALID_PARAM;
1710         }
1711
1712         if (r->in.level > 3) {
1713                 return WERR_INVALID_PARAM;
1714         }
1715         if ((r->in.level == 1 && !r->in.userlevel.level1) ||
1716             (r->in.level == 2 && !r->in.userlevel.level2) ||
1717             (r->in.level == 3 && !r->in.userlevel.level3)) {
1718                 return WERR_INVALID_PARAM;
1719         }
1720
1721         /* some sanity check because you can open a printer or a print server */
1722         /* aka: \\server\printer or \\server */
1723
1724         DEBUGADD(3,("checking name: %s\n", r->in.printername));
1725
1726         result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1727         if (!W_ERROR_IS_OK(result)) {
1728                 DEBUG(0,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1729                         "for printer %s\n", r->in.printername));
1730                 ZERO_STRUCTP(r->out.handle);
1731                 return result;
1732         }
1733
1734         Printer = find_printer_index_by_hnd(p, r->out.handle);
1735         if ( !Printer ) {
1736                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1737                         "handle we created for printer %s\n", r->in.printername));
1738                 close_printer_handle(p, r->out.handle);
1739                 ZERO_STRUCTP(r->out.handle);
1740                 return WERR_INVALID_PARAM;
1741         }
1742
1743         /*
1744          * First case: the user is opening the print server:
1745          *
1746          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1747          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1748          *
1749          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1750          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1751          * or if the user is listed in the smb.conf printer admin parameter.
1752          *
1753          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1754          * client view printer folder, but does not show the MSAPW.
1755          *
1756          * Note: this test needs code to check access rights here too. Jeremy
1757          * could you look at this?
1758          *
1759          * Second case: the user is opening a printer:
1760          * NT doesn't let us connect to a printer if the connecting user
1761          * doesn't have print permission.
1762          *
1763          * Third case: user is opening a Port Monitor
1764          * access checks same as opening a handle to the print server.
1765          */
1766
1767         switch (Printer->printer_type )
1768         {
1769         case SPLHND_SERVER:
1770         case SPLHND_PORTMON_TCP:
1771         case SPLHND_PORTMON_LOCAL:
1772                 /* Printserver handles use global struct... */
1773
1774                 snum = -1;
1775
1776                 /* Map standard access rights to object specific access rights */
1777
1778                 se_map_standard(&r->in.access_mask,
1779                                 &printserver_std_mapping);
1780
1781                 /* Deny any object specific bits that don't apply to print
1782                    servers (i.e printer and job specific bits) */
1783
1784                 r->in.access_mask &= SEC_MASK_SPECIFIC;
1785
1786                 if (r->in.access_mask &
1787                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1788                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1789                         close_printer_handle(p, r->out.handle);
1790                         ZERO_STRUCTP(r->out.handle);
1791                         return WERR_ACCESS_DENIED;
1792                 }
1793
1794                 /* Allow admin access */
1795
1796                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1797                 {
1798                         if (!lp_ms_add_printer_wizard()) {
1799                                 close_printer_handle(p, r->out.handle);
1800                                 ZERO_STRUCTP(r->out.handle);
1801                                 return WERR_ACCESS_DENIED;
1802                         }
1803
1804                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1805                            and not a printer admin, then fail */
1806
1807                         if ((p->session_info->utok.uid != sec_initial_uid()) &&
1808                             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
1809                             !nt_token_check_sid(&global_sid_Builtin_Print_Operators, p->session_info->security_token) &&
1810                             !token_contains_name_in_list(
1811                                     uidtoname(p->session_info->utok.uid),
1812                                     p->session_info->info3->base.domain.string,
1813                                     NULL,
1814                                     p->session_info->security_token,
1815                                     lp_printer_admin(snum))) {
1816                                 close_printer_handle(p, r->out.handle);
1817                                 ZERO_STRUCTP(r->out.handle);
1818                                 DEBUG(3,("access DENIED as user is not root, "
1819                                         "has no printoperator privilege, "
1820                                         "not a member of the printoperator builtin group and "
1821                                         "is not in printer admin list"));
1822                                 return WERR_ACCESS_DENIED;
1823                         }
1824
1825                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1826                 }
1827                 else
1828                 {
1829                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1830                 }
1831
1832                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1833                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1834
1835                 /* We fall through to return WERR_OK */
1836                 break;
1837
1838         case SPLHND_PRINTER:
1839                 /* NT doesn't let us connect to a printer if the connecting user
1840                    doesn't have print permission.  */
1841
1842                 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1843                         close_printer_handle(p, r->out.handle);
1844                         ZERO_STRUCTP(r->out.handle);
1845                         return WERR_BADFID;
1846                 }
1847
1848                 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1849                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1850                 }
1851
1852                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1853
1854                 /* map an empty access mask to the minimum access mask */
1855                 if (r->in.access_mask == 0x0)
1856                         r->in.access_mask = PRINTER_ACCESS_USE;
1857
1858                 /*
1859                  * If we are not serving the printer driver for this printer,
1860                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1861                  * will keep NT clients happy  --jerry
1862                  */
1863
1864                 if (lp_use_client_driver(snum)
1865                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1866                 {
1867                         r->in.access_mask = PRINTER_ACCESS_USE;
1868                 }
1869
1870                 /* check smb.conf parameters and the the sec_desc */
1871
1872                 if (!allow_access(lp_hostsdeny(snum), lp_hostsallow(snum),
1873                                   p->client_id->name, p->client_id->addr)) {
1874                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1875                         ZERO_STRUCTP(r->out.handle);
1876                         return WERR_ACCESS_DENIED;
1877                 }
1878
1879                 if (!user_ok_token(uidtoname(p->session_info->utok.uid), NULL,
1880                                    p->session_info->security_token, snum) ||
1881                     !print_access_check(p->session_info,
1882                                         p->msg_ctx,
1883                                         snum,
1884                                         r->in.access_mask)) {
1885                         DEBUG(3, ("access DENIED for printer open\n"));
1886                         close_printer_handle(p, r->out.handle);
1887                         ZERO_STRUCTP(r->out.handle);
1888                         return WERR_ACCESS_DENIED;
1889                 }
1890
1891                 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1892                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1893                         close_printer_handle(p, r->out.handle);
1894                         ZERO_STRUCTP(r->out.handle);
1895                         return WERR_ACCESS_DENIED;
1896                 }
1897
1898                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1899                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1900                 else
1901                         r->in.access_mask = PRINTER_ACCESS_USE;
1902
1903                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1904                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1905
1906                 winreg_create_printer(p->mem_ctx,
1907                                       get_session_info_system(),
1908                                       p->msg_ctx,
1909                                       lp_const_servicename(snum));
1910
1911                 break;
1912
1913         default:
1914                 /* sanity check to prevent programmer error */
1915                 ZERO_STRUCTP(r->out.handle);
1916                 return WERR_BADFID;
1917         }
1918
1919         Printer->access_granted = r->in.access_mask;
1920
1921         /*
1922          * If the client sent a devmode in the OpenPrinter() call, then
1923          * save it here in case we get a job submission on this handle
1924          */
1925
1926          if ((Printer->printer_type != SPLHND_SERVER) &&
1927              r->in.devmode_ctr.devmode) {
1928                 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1929                                 &Printer->devmode);
1930          }
1931
1932 #if 0   /* JERRY -- I'm doubtful this is really effective */
1933         /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1934            optimization in Windows 2000 clients  --jerry */
1935
1936         if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1937                 && (RA_WIN2K == get_remote_arch()) )
1938         {
1939                 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1940                 sys_usleep( 500000 );
1941         }
1942 #endif
1943
1944         return WERR_OK;
1945 }
1946
1947 /****************************************************************
1948  _spoolss_ClosePrinter
1949 ****************************************************************/
1950
1951 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1952                              struct spoolss_ClosePrinter *r)
1953 {
1954         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1955
1956         if (Printer && Printer->document_started) {
1957                 struct spoolss_EndDocPrinter e;
1958
1959                 e.in.handle = r->in.handle;
1960
1961                 _spoolss_EndDocPrinter(p, &e);
1962         }
1963
1964         if (!close_printer_handle(p, r->in.handle))
1965                 return WERR_BADFID;
1966
1967         /* clear the returned printer handle.  Observed behavior
1968            from Win2k server.  Don't think this really matters.
1969            Previous code just copied the value of the closed
1970            handle.    --jerry */
1971
1972         ZERO_STRUCTP(r->out.handle);
1973
1974         return WERR_OK;
1975 }
1976
1977 /****************************************************************
1978  _spoolss_DeletePrinter
1979 ****************************************************************/
1980
1981 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
1982                               struct spoolss_DeletePrinter *r)
1983 {
1984         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1985         WERROR result;
1986         int snum;
1987
1988         if (Printer && Printer->document_started) {
1989                 struct spoolss_EndDocPrinter e;
1990
1991                 e.in.handle = r->in.handle;
1992
1993                 _spoolss_EndDocPrinter(p, &e);
1994         }
1995
1996         if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
1997                 winreg_delete_printer_key(p->mem_ctx,
1998                                           get_session_info_system(),
1999                                           p->msg_ctx,
2000                                           lp_const_servicename(snum),
2001                                           "");
2002         }
2003
2004         result = delete_printer_handle(p, r->in.handle);
2005
2006         return result;
2007 }
2008
2009 /*******************************************************************
2010  * static function to lookup the version id corresponding to an
2011  * long architecture string
2012  ******************************************************************/
2013
2014 static const struct print_architecture_table_node archi_table[]= {
2015
2016         {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
2017         {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
2018         {"Windows NT R4000",     SPL_ARCH_W32MIPS,      2 },
2019         {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,     2 },
2020         {"Windows NT PowerPC",   SPL_ARCH_W32PPC,       2 },
2021         {"Windows IA64",         SPL_ARCH_IA64,         3 },
2022         {"Windows x64",          SPL_ARCH_X64,          3 },
2023         {NULL,                   "",            -1 }
2024 };
2025
2026 static int get_version_id(const char *arch)
2027 {
2028         int i;
2029
2030         for (i=0; archi_table[i].long_archi != NULL; i++)
2031         {
2032                 if (strcmp(arch, archi_table[i].long_archi) == 0)
2033                         return (archi_table[i].version);
2034         }
2035
2036         return -1;
2037 }
2038
2039 /****************************************************************
2040  _spoolss_DeletePrinterDriver
2041 ****************************************************************/
2042
2043 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2044                                     struct spoolss_DeletePrinterDriver *r)
2045 {
2046
2047         struct spoolss_DriverInfo8 *info = NULL;
2048         struct spoolss_DriverInfo8 *info_win2k = NULL;
2049         int                             version;
2050         WERROR                          status;
2051
2052         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2053            and not a printer admin, then fail */
2054
2055         if ( (p->session_info->utok.uid != sec_initial_uid())
2056              && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2057                 && !token_contains_name_in_list(
2058                         uidtoname(p->session_info->utok.uid),
2059                         p->session_info->info3->base.domain.string,
2060                         NULL,
2061                         p->session_info->security_token,
2062                         lp_printer_admin(-1)) )
2063         {
2064                 return WERR_ACCESS_DENIED;
2065         }
2066
2067         /* check that we have a valid driver name first */
2068
2069         if ((version = get_version_id(r->in.architecture)) == -1)
2070                 return WERR_INVALID_ENVIRONMENT;
2071
2072         status = winreg_get_driver(p->mem_ctx,
2073                                    get_session_info_system(),
2074                                    p->msg_ctx,
2075                                    r->in.architecture, r->in.driver,
2076                                    version, &info);
2077         if (!W_ERROR_IS_OK(status)) {
2078                 /* try for Win2k driver if "Windows NT x86" */
2079
2080                 if ( version == 2 ) {
2081                         version = 3;
2082
2083                         status = winreg_get_driver(p->mem_ctx,
2084                                                    get_session_info_system(),
2085                                                    p->msg_ctx,
2086                                                    r->in.architecture,
2087                                                    r->in.driver,
2088                                                    version, &info);
2089                         if (!W_ERROR_IS_OK(status)) {
2090                                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2091                                 goto done;
2092                         }
2093                 }
2094                 /* otherwise it was a failure */
2095                 else {
2096                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2097                         goto done;
2098                 }
2099
2100         }
2101
2102         if (printer_driver_in_use(p->mem_ctx,
2103                                   get_session_info_system(),
2104                                   p->msg_ctx,
2105                                   info)) {
2106                 status = WERR_PRINTER_DRIVER_IN_USE;
2107                 goto done;
2108         }
2109
2110         if (version == 2) {
2111                 status = winreg_get_driver(p->mem_ctx,
2112                                            get_session_info_system(),
2113                                            p->msg_ctx,
2114                                            r->in.architecture,
2115                                            r->in.driver, 3, &info_win2k);
2116                 if (W_ERROR_IS_OK(status)) {
2117                         /* if we get to here, we now have 2 driver info structures to remove */
2118                         /* remove the Win2k driver first*/
2119
2120                         status = winreg_del_driver(p->mem_ctx,
2121                                                    get_session_info_system(),
2122                                                    p->msg_ctx,
2123                                                    info_win2k, 3);
2124                         talloc_free(info_win2k);
2125
2126                         /* this should not have failed---if it did, report to client */
2127                         if (!W_ERROR_IS_OK(status)) {
2128                                 goto done;
2129                         }
2130                 }
2131         }
2132
2133         status = winreg_del_driver(p->mem_ctx,
2134                                    get_session_info_system(),
2135                                    p->msg_ctx,
2136                                    info, version);
2137
2138 done:
2139         talloc_free(info);
2140
2141         return status;
2142 }
2143
2144 /****************************************************************
2145  _spoolss_DeletePrinterDriverEx
2146 ****************************************************************/
2147
2148 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2149                                       struct spoolss_DeletePrinterDriverEx *r)
2150 {
2151         struct spoolss_DriverInfo8      *info = NULL;
2152         struct spoolss_DriverInfo8      *info_win2k = NULL;
2153         int                             version;
2154         bool                            delete_files;
2155         WERROR                          status;
2156
2157         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2158            and not a printer admin, then fail */
2159
2160         if ( (p->session_info->utok.uid != sec_initial_uid())
2161                 && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2162                 && !token_contains_name_in_list(
2163                         uidtoname(p->session_info->utok.uid),
2164                         p->session_info->info3->base.domain.string,
2165                         NULL,
2166                         p->session_info->security_token, lp_printer_admin(-1)) )
2167         {
2168                 return WERR_ACCESS_DENIED;
2169         }
2170
2171         /* check that we have a valid driver name first */
2172         if ((version = get_version_id(r->in.architecture)) == -1) {
2173                 /* this is what NT returns */
2174                 return WERR_INVALID_ENVIRONMENT;
2175         }
2176
2177         if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2178                 version = r->in.version;
2179
2180         status = winreg_get_driver(p->mem_ctx,
2181                                    get_session_info_system(),
2182                                    p->msg_ctx,
2183                                    r->in.architecture,
2184                                    r->in.driver,
2185                                    version,
2186                                    &info);
2187         if (!W_ERROR_IS_OK(status)) {
2188                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2189
2190                 /*
2191                  * if the client asked for a specific version,
2192                  * or this is something other than Windows NT x86,
2193                  * then we've failed
2194                  */
2195
2196                 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2197                         goto done;
2198
2199                 /* try for Win2k driver if "Windows NT x86" */
2200
2201                 version = 3;
2202                 status = winreg_get_driver(info,
2203                                            get_session_info_system(),
2204                                            p->msg_ctx,
2205                                            r->in.architecture,
2206                                            r->in.driver,
2207                                            version, &info);
2208                 if (!W_ERROR_IS_OK(status)) {
2209                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2210                         goto done;
2211                 }
2212         }
2213
2214         if (printer_driver_in_use(info,
2215                                   get_session_info_system(),
2216                                   p->msg_ctx,
2217                                   info)) {
2218                 status = WERR_PRINTER_DRIVER_IN_USE;
2219                 goto done;
2220         }
2221
2222         /*
2223          * we have a couple of cases to consider.
2224          * (1) Are any files in use?  If so and DPD_DELTE_ALL_FILE is set,
2225          *     then the delete should fail if **any** files overlap with
2226          *     other drivers
2227          * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2228          *     non-overlapping files
2229          * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2230          *     is set, the do not delete any files
2231          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2232          */
2233
2234         delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2235
2236         /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2237
2238         if (delete_files &&
2239             (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2240             printer_driver_files_in_use(info,
2241                                         get_session_info_system(),
2242                                         p->msg_ctx,
2243                                         info)) {
2244                 /* no idea of the correct error here */
2245                 status = WERR_ACCESS_DENIED;
2246                 goto done;
2247         }
2248
2249
2250         /* also check for W32X86/3 if necessary; maybe we already have? */
2251
2252         if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION)  ) {
2253                 status = winreg_get_driver(info,
2254                                            get_session_info_system(),
2255                                            p->msg_ctx,
2256                                            r->in.architecture,
2257                                            r->in.driver, 3, &info_win2k);
2258                 if (W_ERROR_IS_OK(status)) {
2259
2260                         if (delete_files &&
2261                             (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2262                             printer_driver_files_in_use(info,
2263                                                         get_session_info_system(),
2264                                                         p->msg_ctx,
2265                                                         info_win2k)) {
2266                                 /* no idea of the correct error here */
2267                                 talloc_free(info_win2k);
2268                                 status = WERR_ACCESS_DENIED;
2269                                 goto done;
2270                         }
2271
2272                         /* if we get to here, we now have 2 driver info structures to remove */
2273                         /* remove the Win2k driver first*/
2274
2275                         status = winreg_del_driver(info,
2276                                                    get_session_info_system(),
2277                                                    p->msg_ctx,
2278                                                    info_win2k,
2279                                                    3);
2280
2281                         /* this should not have failed---if it did, report to client */
2282
2283                         if (!W_ERROR_IS_OK(status)) {
2284                                 goto done;
2285                         }
2286
2287                         /*
2288                          * now delete any associated files if delete_files is
2289                          * true. Even if this part failes, we return succes
2290                          * because the driver doesn not exist any more
2291                          */
2292                         if (delete_files) {
2293                                 delete_driver_files(get_session_info_system(),
2294                                                     info_win2k);
2295                         }
2296                 }
2297         }
2298
2299         status = winreg_del_driver(info,
2300                                    get_session_info_system(),
2301                                    p->msg_ctx,
2302                                    info,
2303                                    version);
2304         if (!W_ERROR_IS_OK(status)) {
2305                 goto done;
2306         }
2307
2308         /*
2309          * now delete any associated files if delete_files is
2310          * true. Even if this part failes, we return succes
2311          * because the driver doesn not exist any more
2312          */
2313         if (delete_files) {
2314                 delete_driver_files(get_session_info_system(), info);
2315         }
2316
2317 done:
2318         talloc_free(info);
2319         return status;
2320 }
2321
2322
2323 /********************************************************************
2324  GetPrinterData on a printer server Handle.
2325 ********************************************************************/
2326
2327 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2328                                             const char *value,
2329                                             enum winreg_Type *type,
2330                                             union spoolss_PrinterData *data)
2331 {
2332         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2333
2334         if (!StrCaseCmp(value, "W3SvcInstalled")) {
2335                 *type = REG_DWORD;
2336                 data->value = 0x00;
2337                 return WERR_OK;
2338         }
2339
2340         if (!StrCaseCmp(value, "BeepEnabled")) {
2341                 *type = REG_DWORD;
2342                 data->value = 0x00;
2343                 return WERR_OK;
2344         }
2345
2346         if (!StrCaseCmp(value, "EventLog")) {
2347                 *type = REG_DWORD;
2348                 /* formally was 0x1b */
2349                 data->value = 0x00;
2350                 return WERR_OK;
2351         }
2352
2353         if (!StrCaseCmp(value, "NetPopup")) {
2354                 *type = REG_DWORD;
2355                 data->value = 0x00;
2356                 return WERR_OK;
2357         }
2358
2359         if (!StrCaseCmp(value, "MajorVersion")) {
2360                 *type = REG_DWORD;
2361
2362                 /* Windows NT 4.0 seems to not allow uploading of drivers
2363                    to a server that reports 0x3 as the MajorVersion.
2364                    need to investigate more how Win2k gets around this .
2365                    -- jerry */
2366
2367                 if (RA_WINNT == get_remote_arch()) {
2368                         data->value = 0x02;
2369                 } else {
2370                         data->value = 0x03;
2371                 }
2372
2373                 return WERR_OK;
2374         }
2375
2376         if (!StrCaseCmp(value, "MinorVersion")) {
2377                 *type = REG_DWORD;
2378                 data->value = 0x00;
2379                 return WERR_OK;
2380         }
2381
2382         /* REG_BINARY
2383          *  uint32_t size        = 0x114
2384          *  uint32_t major       = 5
2385          *  uint32_t minor       = [0|1]
2386          *  uint32_t build       = [2195|2600]
2387          *  extra unicode string = e.g. "Service Pack 3"
2388          */
2389         if (!StrCaseCmp(value, "OSVersion")) {
2390                 DATA_BLOB blob;
2391                 enum ndr_err_code ndr_err;
2392                 struct spoolss_OSVersion os;
2393
2394                 os.major                = 5;    /* Windows 2000 == 5.0 */
2395                 os.minor                = 0;
2396                 os.build                = 2195; /* build */
2397                 os.extra_string         = "";   /* leave extra string empty */
2398
2399                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2400                         (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2401                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2402                         return WERR_GENERAL_FAILURE;
2403                 }
2404
2405                 *type = REG_BINARY;
2406                 data->binary = blob;
2407
2408                 return WERR_OK;
2409         }
2410
2411
2412         if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2413                 *type = REG_SZ;
2414
2415                 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2416                 W_ERROR_HAVE_NO_MEMORY(data->string);
2417
2418                 return WERR_OK;
2419         }
2420
2421         if (!StrCaseCmp(value, "Architecture")) {
2422                 *type = REG_SZ;
2423                 data->string = talloc_strdup(mem_ctx,
2424                         lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2425                 W_ERROR_HAVE_NO_MEMORY(data->string);
2426
2427                 return WERR_OK;
2428         }
2429
2430         if (!StrCaseCmp(value, "DsPresent")) {
2431                 *type = REG_DWORD;
2432
2433                 /* only show the publish check box if we are a
2434                    member of a AD domain */
2435
2436                 if (lp_security() == SEC_ADS) {
2437                         data->value = 0x01;
2438                 } else {
2439                         data->value = 0x00;
2440                 }
2441                 return WERR_OK;
2442         }
2443
2444         if (!StrCaseCmp(value, "DNSMachineName")) {
2445                 const char *hostname = get_mydnsfullname();
2446
2447                 if (!hostname) {
2448                         return WERR_BADFILE;
2449                 }
2450
2451                 *type = REG_SZ;
2452                 data->string = talloc_strdup(mem_ctx, hostname);
2453                 W_ERROR_HAVE_NO_MEMORY(data->string);
2454
2455                 return WERR_OK;
2456         }
2457
2458         *type = REG_NONE;
2459
2460         return WERR_INVALID_PARAM;
2461 }
2462
2463 /****************************************************************
2464  _spoolss_GetPrinterData
2465 ****************************************************************/
2466
2467 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2468                                struct spoolss_GetPrinterData *r)
2469 {
2470         struct spoolss_GetPrinterDataEx r2;
2471
2472         r2.in.handle            = r->in.handle;
2473         r2.in.key_name          = "PrinterDriverData";
2474         r2.in.value_name        = r->in.value_name;
2475         r2.in.offered           = r->in.offered;
2476         r2.out.type             = r->out.type;
2477         r2.out.data             = r->out.data;
2478         r2.out.needed           = r->out.needed;
2479
2480         return _spoolss_GetPrinterDataEx(p, &r2);
2481 }
2482
2483 /*********************************************************
2484  Connect to the client machine.
2485 **********************************************************/
2486
2487 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2488                         struct sockaddr_storage *client_ss, const char *remote_machine)
2489 {
2490         NTSTATUS ret;
2491         struct cli_state *the_cli;
2492         struct sockaddr_storage rm_addr;
2493         char addr[INET6_ADDRSTRLEN];
2494
2495         if ( is_zero_addr(client_ss) ) {
2496                 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2497                         remote_machine));
2498                 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2499                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2500                         return false;
2501                 }
2502                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2503         } else {
2504                 rm_addr = *client_ss;
2505                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2506                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2507                         addr));
2508         }
2509
2510         if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2511                 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2512                         addr));
2513                 return false;
2514         }
2515
2516         /* setup the connection */
2517         ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2518                 &rm_addr, 0, "IPC$", "IPC",
2519                 "", /* username */
2520                 "", /* domain */
2521                 "", /* password */
2522                 0, lp_client_signing());
2523
2524         if ( !NT_STATUS_IS_OK( ret ) ) {
2525                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2526                         remote_machine ));
2527                 return false;
2528         }
2529
2530         if ( the_cli->protocol != PROTOCOL_NT1 ) {
2531                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2532                 cli_shutdown(the_cli);
2533                 return false;
2534         }
2535
2536         /*
2537          * Ok - we have an anonymous connection to the IPC$ share.
2538          * Now start the NT Domain stuff :-).
2539          */
2540
2541         ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2542         if (!NT_STATUS_IS_OK(ret)) {
2543                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2544                         remote_machine, nt_errstr(ret)));
2545                 cli_shutdown(the_cli);
2546                 return false;
2547         }
2548
2549         return true;
2550 }
2551
2552 /***************************************************************************
2553  Connect to the client.
2554 ****************************************************************************/
2555
2556 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2557                                         uint32_t localprinter,
2558                                         enum winreg_Type type,
2559                                         struct policy_handle *handle,
2560                                         struct notify_back_channel **_chan,
2561                                         struct sockaddr_storage *client_ss,
2562                                         struct messaging_context *msg_ctx)
2563 {
2564         WERROR result;
2565         NTSTATUS status;
2566         struct notify_back_channel *chan;
2567
2568         for (chan = back_channels; chan; chan = chan->next) {
2569                 if (memcmp(&chan->client_address, client_ss,
2570                            sizeof(struct sockaddr_storage)) == 0) {
2571                         break;
2572                 }
2573         }
2574
2575         /*
2576          * If it's the first connection, contact the client
2577          * and connect to the IPC$ share anonymously
2578          */
2579         if (!chan) {
2580                 fstring unix_printer;
2581
2582                 /* the +2 is to strip the leading 2 backslashs */
2583                 fstrcpy(unix_printer, printer + 2);
2584
2585                 chan = talloc_zero(back_channels, struct notify_back_channel);
2586                 if (!chan) {
2587                         return false;
2588                 }
2589                 chan->client_address = *client_ss;
2590
2591                 if (!spoolss_connect_to_client(&chan->cli_pipe, client_ss, unix_printer)) {
2592                         TALLOC_FREE(chan);
2593                         return false;
2594                 }
2595                 chan->binding_handle = chan->cli_pipe->binding_handle;
2596
2597                 DLIST_ADD(back_channels, chan);
2598
2599                 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2600                                    receive_notify2_message_list);
2601                 /* Tell the connections db we're now interested in printer
2602                  * notify messages. */
2603                 serverid_register_msg_flags(messaging_server_id(msg_ctx),
2604                                             true, FLAG_MSG_PRINT_NOTIFY);
2605         }
2606
2607         /*
2608          * Tell the specific printing tdb we want messages for this printer
2609          * by registering our PID.
2610          */
2611
2612         if (!print_notify_register_pid(snum)) {
2613                 DEBUG(0, ("Failed to register our pid for printer %s\n",
2614                           printer));
2615         }
2616
2617         status = dcerpc_spoolss_ReplyOpenPrinter(chan->binding_handle,
2618                                                  talloc_tos(),
2619                                                  printer,
2620                                                  localprinter,
2621                                                  type,
2622                                                  0,
2623                                                  NULL,
2624                                                  handle,
2625                                                  &result);
2626         if (!NT_STATUS_IS_OK(status)) {
2627                 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2628                 result = ntstatus_to_werror(status);
2629         } else if (!W_ERROR_IS_OK(result)) {
2630                 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2631         }
2632
2633         chan->active_connections++;
2634         *_chan = chan;
2635
2636         return (W_ERROR_IS_OK(result));
2637 }
2638
2639 /****************************************************************
2640  ****************************************************************/
2641
2642 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2643                                                              const struct spoolss_NotifyOption *r)
2644 {
2645         struct spoolss_NotifyOption *option;
2646         uint32_t i,k;
2647
2648         if (!r) {
2649                 return NULL;
2650         }
2651
2652         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2653         if (!option) {
2654                 return NULL;
2655         }
2656
2657         *option = *r;
2658
2659         if (!option->count) {
2660                 return option;
2661         }
2662
2663         option->types = talloc_zero_array(option,
2664                 struct spoolss_NotifyOptionType, option->count);
2665         if (!option->types) {
2666                 talloc_free(option);
2667                 return NULL;
2668         }
2669
2670         for (i=0; i < option->count; i++) {
2671                 option->types[i] = r->types[i];
2672
2673                 if (option->types[i].count) {
2674                         option->types[i].fields = talloc_zero_array(option,
2675                                 union spoolss_Field, option->types[i].count);
2676                         if (!option->types[i].fields) {
2677                                 talloc_free(option);
2678                                 return NULL;
2679                         }
2680                         for (k=0; k<option->types[i].count; k++) {
2681                                 option->types[i].fields[k] =
2682                                         r->types[i].fields[k];
2683                         }
2684                 }
2685         }
2686
2687         return option;
2688 }
2689
2690 /****************************************************************
2691  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2692  *
2693  * before replying OK: status=0 a rpc call is made to the workstation
2694  * asking ReplyOpenPrinter
2695  *
2696  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2697  * called from api_spoolss_rffpcnex
2698 ****************************************************************/
2699
2700 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2701                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2702 {
2703         int snum = -1;
2704         struct spoolss_NotifyOption *option = r->in.notify_options;
2705         struct sockaddr_storage client_ss;
2706
2707         /* store the notify value in the printer struct */
2708
2709         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2710
2711         if (!Printer) {
2712                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2713                         "Invalid handle (%s:%u:%u).\n",
2714                         OUR_HANDLE(r->in.handle)));
2715                 return WERR_BADFID;
2716         }
2717
2718         Printer->notify.flags           = r->in.flags;
2719         Printer->notify.options         = r->in.options;
2720         Printer->notify.printerlocal    = r->in.printer_local;
2721         Printer->notify.msg_ctx         = p->msg_ctx;
2722
2723         TALLOC_FREE(Printer->notify.option);
2724         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2725
2726         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2727
2728         /* Connect to the client machine and send a ReplyOpenPrinter */
2729
2730         if ( Printer->printer_type == SPLHND_SERVER)
2731                 snum = -1;
2732         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2733                         !get_printer_snum(p, r->in.handle, &snum, NULL) )
2734                 return WERR_BADFID;
2735
2736         DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2737                 "client_address is %s\n", p->client_id->addr));
2738
2739         if (!lp_print_notify_backchannel(snum)) {
2740                 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2741                         "backchannel disabled\n"));
2742                 return WERR_SERVER_UNAVAILABLE;
2743         }
2744
2745         if (!interpret_string_addr(&client_ss, p->client_id->addr,
2746                                    AI_NUMERICHOST)) {
2747                 return WERR_SERVER_UNAVAILABLE;
2748         }
2749
2750         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2751                                         Printer->notify.printerlocal, REG_SZ,
2752                                         &Printer->notify.cli_hnd,
2753                                         &Printer->notify.cli_chan,
2754                                         &client_ss, p->msg_ctx)) {
2755                 return WERR_SERVER_UNAVAILABLE;
2756         }
2757
2758         return WERR_OK;
2759 }
2760
2761 /*******************************************************************
2762  * fill a notify_info_data with the servername
2763  ********************************************************************/
2764
2765 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2766                                        int snum,
2767                                        struct spoolss_Notify *data,
2768                                        print_queue_struct *queue,
2769                                        struct spoolss_PrinterInfo2 *pinfo2,
2770                                        TALLOC_CTX *mem_ctx)
2771 {
2772         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2773 }
2774
2775 /*******************************************************************
2776  * fill a notify_info_data with the printername (not including the servername).
2777  ********************************************************************/
2778
2779 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2780                                         int snum,
2781                                         struct spoolss_Notify *data,
2782                                         print_queue_struct *queue,
2783                                         struct spoolss_PrinterInfo2 *pinfo2,
2784                                         TALLOC_CTX *mem_ctx)
2785 {
2786         /* the notify name should not contain the \\server\ part */
2787         const char *p = strrchr(pinfo2->printername, '\\');
2788
2789         if (!p) {
2790                 p = pinfo2->printername;
2791         } else {
2792                 p++;
2793         }
2794
2795         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2796 }
2797
2798 /*******************************************************************
2799  * fill a notify_info_data with the servicename
2800  ********************************************************************/
2801
2802 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2803                                       int snum,
2804                                       struct spoolss_Notify *data,
2805                                       print_queue_struct *queue,
2806                                       struct spoolss_PrinterInfo2 *pinfo2,
2807                                       TALLOC_CTX *mem_ctx)
2808 {
2809         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2810 }
2811
2812 /*******************************************************************
2813  * fill a notify_info_data with the port name
2814  ********************************************************************/
2815
2816 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2817                                      int snum,
2818                                      struct spoolss_Notify *data,
2819                                      print_queue_struct *queue,
2820                                      struct spoolss_PrinterInfo2 *pinfo2,
2821                                      TALLOC_CTX *mem_ctx)
2822 {
2823         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2824 }
2825
2826 /*******************************************************************
2827  * fill a notify_info_data with the printername
2828  * but it doesn't exist, have to see what to do
2829  ********************************************************************/
2830
2831 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2832                                        int snum,
2833                                        struct spoolss_Notify *data,
2834                                        print_queue_struct *queue,
2835                                        struct spoolss_PrinterInfo2 *pinfo2,
2836                                        TALLOC_CTX *mem_ctx)
2837 {
2838         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2839 }
2840
2841 /*******************************************************************
2842  * fill a notify_info_data with the comment
2843  ********************************************************************/
2844
2845 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2846                                    int snum,
2847                                    struct spoolss_Notify *data,
2848                                    print_queue_struct *queue,
2849                                    struct spoolss_PrinterInfo2 *pinfo2,
2850                                    TALLOC_CTX *mem_ctx)
2851 {
2852         const char *p;
2853
2854         if (*pinfo2->comment == '\0') {
2855                 p = lp_comment(snum);
2856         } else {
2857                 p = pinfo2->comment;
2858         }
2859
2860         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2861 }
2862
2863 /*******************************************************************
2864  * fill a notify_info_data with the comment
2865  * location = "Room 1, floor 2, building 3"
2866  ********************************************************************/
2867
2868 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2869                                     int snum,
2870                                     struct spoolss_Notify *data,
2871                                     print_queue_struct *queue,
2872                                     struct spoolss_PrinterInfo2 *pinfo2,
2873                                     TALLOC_CTX *mem_ctx)
2874 {
2875         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->location);
2876 }
2877
2878 /*******************************************************************
2879  * fill a notify_info_data with the device mode
2880  * jfm:xxxx don't to it for know but that's a real problem !!!
2881  ********************************************************************/
2882
2883 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2884                                    int snum,
2885                                    struct spoolss_Notify *data,
2886                                    print_queue_struct *queue,
2887                                    struct spoolss_PrinterInfo2 *pinfo2,
2888                                    TALLOC_CTX *mem_ctx)
2889 {
2890         /* for a dummy implementation we have to zero the fields */
2891         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2892 }
2893
2894 /*******************************************************************
2895  * fill a notify_info_data with the separator file name
2896  ********************************************************************/
2897
2898 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2899                                    int snum,
2900                                    struct spoolss_Notify *data,
2901                                    print_queue_struct *queue,
2902                                    struct spoolss_PrinterInfo2 *pinfo2,
2903                                    TALLOC_CTX *mem_ctx)
2904 {
2905         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2906 }
2907
2908 /*******************************************************************
2909  * fill a notify_info_data with the print processor
2910  * jfm:xxxx return always winprint to indicate we don't do anything to it
2911  ********************************************************************/
2912
2913 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2914                                            int snum,
2915                                            struct spoolss_Notify *data,
2916                                            print_queue_struct *queue,
2917                                            struct spoolss_PrinterInfo2 *pinfo2,
2918                                            TALLOC_CTX *mem_ctx)
2919 {
2920         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2921 }
2922
2923 /*******************************************************************
2924  * fill a notify_info_data with the print processor options
2925  * jfm:xxxx send an empty string
2926  ********************************************************************/
2927
2928 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2929                                       int snum,
2930                                       struct spoolss_Notify *data,
2931                                       print_queue_struct *queue,
2932                                       struct spoolss_PrinterInfo2 *pinfo2,
2933                                       TALLOC_CTX *mem_ctx)
2934 {
2935         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2936 }
2937
2938 /*******************************************************************
2939  * fill a notify_info_data with the data type
2940  * jfm:xxxx always send RAW as data type
2941  ********************************************************************/
2942
2943 static void spoolss_notify_datatype(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         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2951 }
2952
2953 /*******************************************************************
2954  * fill a notify_info_data with the security descriptor
2955  * jfm:xxxx send an null pointer to say no security desc
2956  * have to implement security before !
2957  ********************************************************************/
2958
2959 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2960                                          int snum,
2961                                          struct spoolss_Notify *data,
2962                                          print_queue_struct *queue,
2963                                          struct spoolss_PrinterInfo2 *pinfo2,
2964                                          TALLOC_CTX *mem_ctx)
2965 {
2966         SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
2967 }
2968
2969 /*******************************************************************
2970  * fill a notify_info_data with the attributes
2971  * jfm:xxxx a samba printer is always shared
2972  ********************************************************************/
2973
2974 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2975                                       int snum,
2976                                       struct spoolss_Notify *data,
2977                                       print_queue_struct *queue,
2978                                       struct spoolss_PrinterInfo2 *pinfo2,
2979                                       TALLOC_CTX *mem_ctx)
2980 {
2981         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2982 }
2983
2984 /*******************************************************************
2985  * fill a notify_info_data with the priority
2986  ********************************************************************/
2987
2988 static void spoolss_notify_priority(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_INTEGER(data, pinfo2->priority);
2996 }
2997
2998 /*******************************************************************
2999  * fill a notify_info_data with the default priority
3000  ********************************************************************/
3001
3002 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
3003                                             int snum,
3004                                             struct spoolss_Notify *data,
3005                                             print_queue_struct *queue,
3006                                             struct spoolss_PrinterInfo2 *pinfo2,
3007                                             TALLOC_CTX *mem_ctx)
3008 {
3009         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
3010 }
3011
3012 /*******************************************************************
3013  * fill a notify_info_data with the start time
3014  ********************************************************************/
3015
3016 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
3017                                       int snum,
3018                                       struct spoolss_Notify *data,
3019                                       print_queue_struct *queue,
3020                                       struct spoolss_PrinterInfo2 *pinfo2,
3021                                       TALLOC_CTX *mem_ctx)
3022 {
3023         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3024 }
3025
3026 /*******************************************************************
3027  * fill a notify_info_data with the until time
3028  ********************************************************************/
3029
3030 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3031                                       int snum,
3032                                       struct spoolss_Notify *data,
3033                                       print_queue_struct *queue,
3034                                       struct spoolss_PrinterInfo2 *pinfo2,
3035                                       TALLOC_CTX *mem_ctx)
3036 {
3037         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3038 }
3039
3040 /*******************************************************************
3041  * fill a notify_info_data with the status
3042  ********************************************************************/
3043
3044 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3045                                   int snum,
3046                                   struct spoolss_Notify *data,
3047                                   print_queue_struct *queue,
3048                                   struct spoolss_PrinterInfo2 *pinfo2,
3049                                   TALLOC_CTX *mem_ctx)
3050 {
3051         print_status_struct status;
3052
3053         print_queue_length(msg_ctx, snum, &status);
3054         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3055 }
3056
3057 /*******************************************************************
3058  * fill a notify_info_data with the number of jobs queued
3059  ********************************************************************/
3060
3061 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3062                                  int snum,
3063                                  struct spoolss_Notify *data,
3064                                  print_queue_struct *queue,
3065                                  struct spoolss_PrinterInfo2 *pinfo2,
3066                                  TALLOC_CTX *mem_ctx)
3067 {
3068         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3069                 data, print_queue_length(msg_ctx, snum, NULL));
3070 }
3071
3072 /*******************************************************************
3073  * fill a notify_info_data with the average ppm
3074  ********************************************************************/
3075
3076 static void spoolss_notify_average_ppm(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         /* always respond 8 pages per minutes */
3084         /* a little hard ! */
3085         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3086 }
3087
3088 /*******************************************************************
3089  * fill a notify_info_data with username
3090  ********************************************************************/
3091
3092 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3093                                     int snum,
3094                                     struct spoolss_Notify *data,
3095                                     print_queue_struct *queue,
3096                                     struct spoolss_PrinterInfo2 *pinfo2,
3097                                     TALLOC_CTX *mem_ctx)
3098 {
3099         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3100 }
3101
3102 /*******************************************************************
3103  * fill a notify_info_data with job status
3104  ********************************************************************/
3105
3106 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3107                                       int snum,
3108                                       struct spoolss_Notify *data,
3109                                       print_queue_struct *queue,
3110                                       struct spoolss_PrinterInfo2 *pinfo2,
3111                                       TALLOC_CTX *mem_ctx)
3112 {
3113         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3114 }
3115
3116 /*******************************************************************
3117  * fill a notify_info_data with job name
3118  ********************************************************************/
3119
3120 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3121                                     int snum,
3122                                     struct spoolss_Notify *data,
3123                                     print_queue_struct *queue,
3124                                     struct spoolss_PrinterInfo2 *pinfo2,
3125                                     TALLOC_CTX *mem_ctx)
3126 {
3127         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3128 }
3129
3130 /*******************************************************************
3131  * fill a notify_info_data with job status
3132  ********************************************************************/
3133
3134 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3135                                              int snum,
3136                                              struct spoolss_Notify *data,
3137                                              print_queue_struct *queue,
3138                                              struct spoolss_PrinterInfo2 *pinfo2,
3139                                              TALLOC_CTX *mem_ctx)
3140 {
3141         /*
3142          * Now we're returning job status codes we just return a "" here. JRA.
3143          */
3144
3145         const char *p = "";
3146
3147 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3148         p = "unknown";
3149
3150         switch (queue->status) {
3151         case LPQ_QUEUED:
3152                 p = "Queued";
3153                 break;
3154         case LPQ_PAUSED:
3155                 p = "";    /* NT provides the paused string */
3156                 break;
3157         case LPQ_SPOOLING:
3158                 p = "Spooling";
3159                 break;
3160         case LPQ_PRINTING:
3161                 p = "Printing";
3162                 break;
3163         }
3164 #endif /* NO LONGER NEEDED. */
3165
3166         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3167 }
3168
3169 /*******************************************************************
3170  * fill a notify_info_data with job time
3171  ********************************************************************/
3172
3173 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3174                                     int snum,
3175                                     struct spoolss_Notify *data,
3176                                     print_queue_struct *queue,
3177                                     struct spoolss_PrinterInfo2 *pinfo2,
3178                                     TALLOC_CTX *mem_ctx)
3179 {
3180         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3181 }
3182
3183 /*******************************************************************
3184  * fill a notify_info_data with job size
3185  ********************************************************************/
3186
3187 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3188                                     int snum,
3189                                     struct spoolss_Notify *data,
3190                                     print_queue_struct *queue,
3191                                     struct spoolss_PrinterInfo2 *pinfo2,
3192                                     TALLOC_CTX *mem_ctx)
3193 {
3194         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3195 }
3196
3197 /*******************************************************************
3198  * fill a notify_info_data with page info
3199  ********************************************************************/
3200 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3201                                        int snum,
3202                                 struct spoolss_Notify *data,
3203                                 print_queue_struct *queue,
3204                                 struct spoolss_PrinterInfo2 *pinfo2,
3205                                 TALLOC_CTX *mem_ctx)
3206 {
3207         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3208 }
3209
3210 /*******************************************************************
3211  * fill a notify_info_data with pages printed info.
3212  ********************************************************************/
3213 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3214                                          int snum,
3215                                 struct spoolss_Notify *data,
3216                                 print_queue_struct *queue,
3217                                 struct spoolss_PrinterInfo2 *pinfo2,
3218                                 TALLOC_CTX *mem_ctx)
3219 {
3220         /* Add code when back-end tracks this */
3221         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3222 }
3223
3224 /*******************************************************************
3225  Fill a notify_info_data with job position.
3226  ********************************************************************/
3227
3228 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3229                                         int snum,
3230                                         struct spoolss_Notify *data,
3231                                         print_queue_struct *queue,
3232                                         struct spoolss_PrinterInfo2 *pinfo2,
3233                                         TALLOC_CTX *mem_ctx)
3234 {
3235         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3236 }
3237
3238 /*******************************************************************
3239  Fill a notify_info_data with submitted time.
3240  ********************************************************************/
3241
3242 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3243                                           int snum,
3244                                           struct spoolss_Notify *data,
3245                                           print_queue_struct *queue,
3246                                           struct spoolss_PrinterInfo2 *pinfo2,
3247                                           TALLOC_CTX *mem_ctx)
3248 {
3249         data->data.string.string = NULL;
3250         data->data.string.size = 0;
3251
3252         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3253                                &data->data.string.string,
3254                                &data->data.string.size);
3255
3256 }
3257
3258 struct s_notify_info_data_table
3259 {
3260         enum spoolss_NotifyType type;
3261         uint16_t field;
3262         const char *name;
3263         enum spoolss_NotifyTable variable_type;
3264         void (*fn) (struct messaging_context *msg_ctx,
3265                     int snum, struct spoolss_Notify *data,
3266                     print_queue_struct *queue,
3267                     struct spoolss_PrinterInfo2 *pinfo2,
3268                     TALLOC_CTX *mem_ctx);
3269 };
3270
3271 /* A table describing the various print notification constants and
3272    whether the notification data is a pointer to a variable sized
3273    buffer, a one value uint32_t or a two value uint32_t. */
3274
3275 static const struct s_notify_info_data_table notify_info_data_table[] =
3276 {
3277 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME,         "PRINTER_NOTIFY_FIELD_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3278 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME,        "PRINTER_NOTIFY_FIELD_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3279 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME,          "PRINTER_NOTIFY_FIELD_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
3280 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME,           "PRINTER_NOTIFY_FIELD_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3281 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME,         "PRINTER_NOTIFY_FIELD_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3282 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT,             "PRINTER_NOTIFY_FIELD_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
3283 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION,            "PRINTER_NOTIFY_FIELD_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
3284 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE,             "PRINTER_NOTIFY_FIELD_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3285 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE,             "PRINTER_NOTIFY_FIELD_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
3286 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR,     "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3287 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS,          "PRINTER_NOTIFY_FIELD_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3288 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE,            "PRINTER_NOTIFY_FIELD_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3289 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
3290 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES,          "PRINTER_NOTIFY_FIELD_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
3291 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY,            "PRINTER_NOTIFY_FIELD_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3292 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
3293 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME,          "PRINTER_NOTIFY_FIELD_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3294 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME,          "PRINTER_NOTIFY_FIELD_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3295 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS,              "PRINTER_NOTIFY_FIELD_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
3296 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING,       "PRINTER_NOTIFY_FIELD_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
3297 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS,               "PRINTER_NOTIFY_FIELD_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
3298 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM,         "PRINTER_NOTIFY_FIELD_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
3299 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES,         "PRINTER_NOTIFY_FIELD_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
3300 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED,       "PRINTER_NOTIFY_FIELD_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3301 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES,         "PRINTER_NOTIFY_FIELD_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
3302 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED,       "PRINTER_NOTIFY_FIELD_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3303 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINTER_NAME,            "JOB_NOTIFY_FIELD_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3304 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_MACHINE_NAME,            "JOB_NOTIFY_FIELD_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3305 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PORT_NAME,               "JOB_NOTIFY_FIELD_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3306 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_USER_NAME,               "JOB_NOTIFY_FIELD_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
3307 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_NOTIFY_NAME,             "JOB_NOTIFY_FIELD_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
3308 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DATATYPE,                "JOB_NOTIFY_FIELD_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3309 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINT_PROCESSOR,         "JOB_NOTIFY_FIELD_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3310 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PARAMETERS,              "JOB_NOTIFY_FIELD_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3311 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DRIVER_NAME,             "JOB_NOTIFY_FIELD_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3312 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DEVMODE,                 "JOB_NOTIFY_FIELD_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3313 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS,                  "JOB_NOTIFY_FIELD_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
3314 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS_STRING,           "JOB_NOTIFY_FIELD_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
3315 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
3316 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DOCUMENT,                "JOB_NOTIFY_FIELD_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
3317 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRIORITY,                "JOB_NOTIFY_FIELD_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3318 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_POSITION,                "JOB_NOTIFY_FIELD_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
3319 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SUBMITTED,               "JOB_NOTIFY_FIELD_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
3320 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_START_TIME,              "JOB_NOTIFY_FIELD_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3321 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_UNTIL_TIME,              "JOB_NOTIFY_FIELD_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3322 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TIME,                    "JOB_NOTIFY_FIELD_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
3323 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_PAGES,             "JOB_NOTIFY_FIELD_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
3324 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PAGES_PRINTED,           "JOB_NOTIFY_FIELD_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
3325 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_BYTES,             "JOB_NOTIFY_FIELD_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
3326 };
3327
3328 /*******************************************************************
3329  Return the variable_type of info_data structure.
3330 ********************************************************************/
3331
3332 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3333                                                                   uint16_t field)
3334 {
3335         int i=0;
3336
3337         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3338                 if ( (notify_info_data_table[i].type == type) &&
3339                      (notify_info_data_table[i].field == field) ) {
3340                         return notify_info_data_table[i].variable_type;
3341                 }
3342         }
3343
3344         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3345
3346         return (enum spoolss_NotifyTable) 0;
3347 }
3348
3349 /****************************************************************************
3350 ****************************************************************************/
3351
3352 static bool search_notify(enum spoolss_NotifyType type,
3353                           uint16_t field,
3354                           int *value)
3355 {
3356         int i;
3357
3358         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3359                 if (notify_info_data_table[i].type == type &&
3360                     notify_info_data_table[i].field == field &&
3361                     notify_info_data_table[i].fn != NULL) {
3362                         *value = i;
3363                         return true;
3364                 }
3365         }
3366
3367         return false;
3368 }
3369
3370 /****************************************************************************
3371 ****************************************************************************/
3372
3373 static void construct_info_data(struct spoolss_Notify *info_data,
3374                                 enum spoolss_NotifyType type,
3375                                 uint16_t field, int id)
3376 {
3377         info_data->type                 = type;
3378         info_data->field.field          = field;
3379         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3380         info_data->job_id               = id;
3381 }
3382
3383 /*******************************************************************
3384  *
3385  * fill a notify_info struct with info asked
3386  *
3387  ********************************************************************/
3388
3389 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3390                                           struct printer_handle *print_hnd,
3391                                           struct spoolss_NotifyInfo *info,
3392                                           struct spoolss_PrinterInfo2 *pinfo2,
3393                                           int snum,
3394                                           const struct spoolss_NotifyOptionType *option_type,
3395                                           uint32_t id,
3396                                           TALLOC_CTX *mem_ctx)
3397 {
3398         int field_num,j;
3399         enum spoolss_NotifyType type;
3400         uint16_t field;
3401
3402         struct spoolss_Notify *current_data;
3403         print_queue_struct *queue=NULL;
3404
3405         type = option_type->type;
3406
3407         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3408                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3409                 option_type->count, lp_servicename(snum)));
3410
3411         for(field_num=0; field_num < option_type->count; field_num++) {
3412                 field = option_type->fields[field_num].field;
3413
3414                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3415
3416                 if (!search_notify(type, field, &j) )
3417                         continue;
3418
3419                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3420                                                       struct spoolss_Notify,
3421                                                       info->count + 1);
3422                 if (info->notifies == NULL) {
3423                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3424                         return false;
3425                 }
3426
3427                 current_data = &info->notifies[info->count];
3428
3429                 construct_info_data(current_data, type, field, id);
3430
3431                 DEBUG(10, ("construct_notify_printer_info: "
3432                            "calling [%s]  snum=%d  printername=[%s])\n",
3433                            notify_info_data_table[j].name, snum,
3434                            pinfo2->printername));
3435
3436                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3437                                              queue, pinfo2, mem_ctx);
3438
3439                 info->count++;
3440         }
3441
3442         return true;
3443 }
3444
3445 /*******************************************************************
3446  *
3447  * fill a notify_info struct with info asked
3448  *
3449  ********************************************************************/
3450
3451 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3452                                        print_queue_struct *queue,
3453                                        struct spoolss_NotifyInfo *info,
3454                                        struct spoolss_PrinterInfo2 *pinfo2,
3455                                        int snum,
3456                                        const struct spoolss_NotifyOptionType *option_type,
3457                                        uint32_t id,
3458                                        TALLOC_CTX *mem_ctx)
3459 {
3460         int field_num,j;
3461         enum spoolss_NotifyType type;
3462         uint16_t field;
3463         struct spoolss_Notify *current_data;
3464
3465         DEBUG(4,("construct_notify_jobs_info\n"));
3466
3467         type = option_type->type;
3468
3469         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3470                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3471                 option_type->count));
3472
3473         for(field_num=0; field_num<option_type->count; field_num++) {
3474                 field = option_type->fields[field_num].field;
3475
3476                 if (!search_notify(type, field, &j) )
3477                         continue;
3478
3479                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3480                                                       struct spoolss_Notify,
3481                                                       info->count + 1);
3482                 if (info->notifies == NULL) {
3483                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3484                         return false;
3485                 }
3486
3487                 current_data=&(info->notifies[info->count]);
3488
3489                 construct_info_data(current_data, type, field, id);
3490                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3491                                              queue, pinfo2, mem_ctx);
3492                 info->count++;
3493         }
3494
3495         return true;
3496 }
3497
3498 /*
3499  * JFM: The enumeration is not that simple, it's even non obvious.
3500  *
3501  * let's take an example: I want to monitor the PRINTER SERVER for
3502  * the printer's name and the number of jobs currently queued.
3503  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3504  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3505  *
3506  * I have 3 printers on the back of my server.
3507  *
3508  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3509  * structures.
3510  *   Number     Data                    Id
3511  *      1       printer 1 name          1
3512  *      2       printer 1 cjob          1
3513  *      3       printer 2 name          2
3514  *      4       printer 2 cjob          2
3515  *      5       printer 3 name          3
3516  *      6       printer 3 name          3
3517  *
3518  * that's the print server case, the printer case is even worse.
3519  */
3520
3521 /*******************************************************************
3522  *
3523  * enumerate all printers on the printserver
3524  * fill a notify_info struct with info asked
3525  *
3526  ********************************************************************/
3527
3528 static WERROR printserver_notify_info(struct pipes_struct *p,
3529                                       struct policy_handle *hnd,
3530                                       struct spoolss_NotifyInfo *info,
3531                                       TALLOC_CTX *mem_ctx)
3532 {
3533         int snum;
3534         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3535         int n_services=lp_numservices();
3536         int i;
3537         struct spoolss_NotifyOption *option;
3538         struct spoolss_NotifyOptionType option_type;
3539         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3540         WERROR result;
3541
3542         DEBUG(4,("printserver_notify_info\n"));
3543
3544         if (!Printer)
3545                 return WERR_BADFID;
3546
3547         option = Printer->notify.option;
3548
3549         info->version   = 2;
3550         info->notifies  = NULL;
3551         info->count     = 0;
3552
3553         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3554            sending a ffpcn() request first */
3555
3556         if ( !option )
3557                 return WERR_BADFID;
3558
3559         for (i=0; i<option->count; i++) {
3560                 option_type = option->types[i];
3561
3562                 if (option_type.type != PRINTER_NOTIFY_TYPE)
3563                         continue;
3564
3565                 for (snum = 0; snum < n_services; snum++) {
3566                         if (!lp_browseable(snum) ||
3567                             !lp_snum_ok(snum) ||
3568                             !lp_print_ok(snum)) {
3569                                 continue; /* skip */
3570                         }
3571
3572                         /* Maybe we should use the SYSTEM session_info here... */
3573                         result = winreg_get_printer(mem_ctx,
3574                                                     get_session_info_system(),
3575                                                     p->msg_ctx,
3576                                                     lp_servicename(snum),
3577                                                     &pinfo2);
3578                         if (!W_ERROR_IS_OK(result)) {
3579                                 DEBUG(4, ("printserver_notify_info: "
3580                                           "Failed to get printer [%s]\n",
3581                                           lp_servicename(snum)));
3582                                 continue;
3583                         }
3584
3585
3586                         construct_notify_printer_info(p->msg_ctx,
3587                                                       Printer, info,
3588                                                       pinfo2, snum,
3589                                                       &option_type, snum,
3590                                                       mem_ctx);
3591
3592                         TALLOC_FREE(pinfo2);
3593                 }
3594         }
3595
3596 #if 0
3597         /*
3598          * Debugging information, don't delete.
3599          */
3600
3601         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3602         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3603         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3604
3605         for (i=0; i<info->count; i++) {
3606                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3607                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3608                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3609         }
3610 #endif
3611
3612         return WERR_OK;
3613 }
3614
3615 /*******************************************************************
3616  *
3617  * fill a notify_info struct with info asked
3618  *
3619  ********************************************************************/
3620
3621 static WERROR printer_notify_info(struct pipes_struct *p,
3622                                   struct policy_handle *hnd,
3623                                   struct spoolss_NotifyInfo *info,
3624                                   TALLOC_CTX *mem_ctx)
3625 {
3626         int snum;
3627         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3628         int i;
3629         uint32_t id;
3630         struct spoolss_NotifyOption *option;
3631         struct spoolss_NotifyOptionType option_type;
3632         int count,j;
3633         print_queue_struct *queue=NULL;
3634         print_status_struct status;
3635         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3636         WERROR result;
3637
3638         DEBUG(4,("printer_notify_info\n"));
3639
3640         if (!Printer)
3641                 return WERR_BADFID;
3642
3643         option = Printer->notify.option;
3644         id = 0x0;
3645
3646         info->version   = 2;
3647         info->notifies  = NULL;
3648         info->count     = 0;
3649
3650         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3651            sending a ffpcn() request first */
3652
3653         if ( !option )
3654                 return WERR_BADFID;
3655
3656         if (!get_printer_snum(p, hnd, &snum, NULL)) {
3657                 return WERR_BADFID;
3658         }
3659
3660         /* Maybe we should use the SYSTEM session_info here... */
3661         result = winreg_get_printer(mem_ctx,
3662                                     get_session_info_system(),
3663                                     p->msg_ctx,
3664                                     lp_servicename(snum), &pinfo2);
3665         if (!W_ERROR_IS_OK(result)) {
3666                 return WERR_BADFID;
3667         }
3668
3669         for (i=0; i<option->count; i++) {
3670                 option_type = option->types[i];
3671
3672                 switch (option_type.type) {
3673                 case PRINTER_NOTIFY_TYPE:
3674                         if (construct_notify_printer_info(p->msg_ctx,
3675                                                           Printer, info,
3676                                                           pinfo2, snum,
3677                                                           &option_type, id,
3678                                                           mem_ctx)) {
3679                                 id--;
3680                         }
3681                         break;
3682
3683                 case JOB_NOTIFY_TYPE:
3684
3685                         count = print_queue_status(p->msg_ctx, snum, &queue,
3686                                                    &status);
3687
3688                         for (j=0; j<count; j++) {
3689                                 construct_notify_jobs_info(p->msg_ctx,
3690                                                            &queue[j], info,
3691                                                            pinfo2, snum,
3692                                                            &option_type,
3693                                                            queue[j].job,
3694                                                            mem_ctx);
3695                         }
3696
3697                         SAFE_FREE(queue);
3698                         break;
3699                 }
3700         }
3701
3702         /*
3703          * Debugging information, don't delete.
3704          */
3705         /*
3706         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3707         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3708         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3709
3710         for (i=0; i<info->count; i++) {
3711                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3712                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3713                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3714         }
3715         */
3716
3717         talloc_free(pinfo2);
3718         return WERR_OK;
3719 }
3720
3721 /****************************************************************
3722  _spoolss_RouterRefreshPrinterChangeNotify
3723 ****************************************************************/
3724
3725 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3726                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3727 {
3728         struct spoolss_NotifyInfo *info;
3729
3730         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3731         WERROR result = WERR_BADFID;
3732
3733         /* we always have a spoolss_NotifyInfo struct */
3734         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3735         if (!info) {
3736                 result = WERR_NOMEM;
3737                 goto done;
3738         }
3739
3740         *r->out.info = info;
3741
3742         if (!Printer) {
3743                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3744                         "Invalid handle (%s:%u:%u).\n",
3745                         OUR_HANDLE(r->in.handle)));
3746                 goto done;
3747         }
3748
3749         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3750
3751         /*
3752          *      We are now using the change value, and
3753          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3754          *      I don't have a global notification system, I'm sending back all the
3755          *      information even when _NOTHING_ has changed.
3756          */
3757
3758         /* We need to keep track of the change value to send back in
3759            RRPCN replies otherwise our updates are ignored. */
3760
3761         Printer->notify.fnpcn = true;
3762
3763         if (Printer->notify.cli_chan != NULL &&
3764             Printer->notify.cli_chan->active_connections > 0) {
3765                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3766                         "Saving change value in request [%x]\n",
3767                         r->in.change_low));
3768                 Printer->notify.change = r->in.change_low;
3769         }
3770
3771         /* just ignore the spoolss_NotifyOption */
3772
3773         switch (Printer->printer_type) {
3774                 case SPLHND_SERVER:
3775                         result = printserver_notify_info(p, r->in.handle,
3776                                                          info, p->mem_ctx);
3777                         break;
3778
3779                 case SPLHND_PRINTER:
3780                         result = printer_notify_info(p, r->in.handle,
3781                                                      info, p->mem_ctx);
3782                         break;
3783         }
3784
3785         Printer->notify.fnpcn = false;
3786
3787 done:
3788         return result;
3789 }
3790
3791 /********************************************************************
3792  ********************************************************************/
3793
3794 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3795                                  const char *servername,
3796                                  const char *printername,
3797                                  const char **printername_p)
3798 {
3799         /* FIXME: add lp_force_printername() */
3800
3801         if (servername == NULL) {
3802                 *printername_p = talloc_strdup(mem_ctx, printername);
3803                 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3804                 return WERR_OK;
3805         }
3806
3807         if (servername[0] == '\\' && servername[1] == '\\') {
3808                 servername += 2;
3809         }
3810
3811         *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3812         W_ERROR_HAVE_NO_MEMORY(*printername_p);
3813
3814         return WERR_OK;
3815 }
3816
3817 /********************************************************************
3818  ********************************************************************/
3819
3820 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3821                                           const char *printername)
3822 {
3823         if (dm == NULL) {
3824                 return;
3825         }
3826
3827         dm->devicename = talloc_strndup(dm, printername,
3828                                         MIN(strlen(printername), 31));
3829 }
3830
3831 /********************************************************************
3832  * construct_printer_info_0
3833  * fill a printer_info_0 struct
3834  ********************************************************************/
3835
3836 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3837                                       const struct auth_serversupplied_info *session_info,
3838                                       struct messaging_context *msg_ctx,
3839                                       struct spoolss_PrinterInfo2 *info2,
3840                                       const char *servername,
3841                                       struct spoolss_PrinterInfo0 *r,
3842                                       int snum)
3843 {
3844         int count;
3845         struct printer_session_counter *session_counter;
3846         struct timeval setuptime;
3847         print_status_struct status;
3848         WERROR result;
3849
3850         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3851         if (!W_ERROR_IS_OK(result)) {
3852                 return result;
3853         }
3854
3855         if (servername) {
3856                 r->servername = talloc_strdup(mem_ctx, servername);
3857                 W_ERROR_HAVE_NO_MEMORY(r->servername);
3858         } else {
3859                 r->servername = NULL;
3860         }
3861
3862         count = print_queue_length(msg_ctx, snum, &status);
3863
3864         /* check if we already have a counter for this printer */
3865         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3866                 if (session_counter->snum == snum)
3867                         break;
3868         }
3869
3870         /* it's the first time, add it to the list */
3871         if (session_counter == NULL) {
3872                 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3873                 W_ERROR_HAVE_NO_MEMORY(session_counter);
3874                 session_counter->snum           = snum;
3875                 session_counter->counter        = 0;
3876                 DLIST_ADD(counter_list, session_counter);
3877         }
3878
3879         /* increment it */
3880         session_counter->counter++;
3881
3882         r->cjobs                        = count;
3883         r->total_jobs                   = 0;
3884         r->total_bytes                  = 0;
3885
3886         get_startup_time(&setuptime);
3887         init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3888
3889         /* JFM:
3890          * the global_counter should be stored in a TDB as it's common to all the clients
3891          * and should be zeroed on samba startup
3892          */
3893         r->global_counter               = session_counter->counter;
3894         r->total_pages                  = 0;
3895         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3896         SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3897         SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3898         r->free_build                   = SPOOLSS_RELEASE_BUILD;
3899         r->spooling                     = 0;
3900         r->max_spooling                 = 0;
3901         r->session_counter              = session_counter->counter;
3902         r->num_error_out_of_paper       = 0x0;
3903         r->num_error_not_ready          = 0x0;          /* number of print failure */
3904         r->job_error                    = 0x0;
3905         r->number_of_processors         = 0x1;
3906         r->processor_type               = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3907         r->high_part_total_bytes        = 0x0;
3908
3909         /* ChangeID in milliseconds*/
3910         winreg_printer_get_changeid(mem_ctx, session_info, msg_ctx,
3911                                     info2->sharename, &r->change_id);
3912
3913         r->last_error                   = WERR_OK;
3914         r->status                       = nt_printq_status(status.status);
3915         r->enumerate_network_printers   = 0x0;
3916         r->c_setprinter                 = 0x0;
3917         r->processor_architecture       = PROCESSOR_ARCHITECTURE_INTEL;
3918         r->processor_level              = 0x6;          /* 6  ???*/
3919         r->ref_ic                       = 0;
3920         r->reserved2                    = 0;
3921         r->reserved3                    = 0;
3922
3923         return WERR_OK;
3924 }
3925
3926
3927 /********************************************************************
3928  * construct_printer_info1
3929  * fill a spoolss_PrinterInfo1 struct
3930 ********************************************************************/
3931
3932 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3933                                       const struct spoolss_PrinterInfo2 *info2,
3934                                       uint32_t flags,
3935                                       const char *servername,
3936                                       struct spoolss_PrinterInfo1 *r,
3937                                       int snum)
3938 {
3939         WERROR result;
3940
3941         r->flags                = flags;
3942
3943         if (info2->comment == NULL || info2->comment[0] == '\0') {
3944                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
3945         } else {
3946                 r->comment      = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3947         }
3948         W_ERROR_HAVE_NO_MEMORY(r->comment);
3949
3950         result = create_printername(mem_ctx, servername, info2->printername, &r->name);
3951         if (!W_ERROR_IS_OK(result)) {
3952                 return result;
3953         }
3954
3955         r->description          = talloc_asprintf(mem_ctx, "%s,%s,%s",
3956                                                   r->name,
3957                                                   info2->drivername,
3958                                                   r->comment);
3959         W_ERROR_HAVE_NO_MEMORY(r->description);
3960
3961         return WERR_OK;
3962 }
3963
3964 /********************************************************************
3965  * construct_printer_info2
3966  * fill a spoolss_PrinterInfo2 struct
3967 ********************************************************************/
3968
3969 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3970                                       struct messaging_context *msg_ctx,
3971                                       const struct spoolss_PrinterInfo2 *info2,
3972                                       const char *servername,
3973                                       struct spoolss_PrinterInfo2 *r,
3974                                       int snum)
3975 {
3976         int count;
3977         print_status_struct status;
3978         WERROR result;
3979
3980         count = print_queue_length(msg_ctx, snum, &status);
3981
3982         if (servername) {
3983                 r->servername           = talloc_strdup(mem_ctx, servername);
3984                 W_ERROR_HAVE_NO_MEMORY(r->servername);
3985         } else {
3986                 r->servername           = NULL;
3987         }
3988
3989         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3990         if (!W_ERROR_IS_OK(result)) {
3991                 return result;
3992         }
3993
3994         r->sharename            = talloc_strdup(mem_ctx, lp_servicename(snum));
3995         W_ERROR_HAVE_NO_MEMORY(r->sharename);
3996         r->portname             = talloc_strdup(mem_ctx, info2->portname);
3997         W_ERROR_HAVE_NO_MEMORY(r->portname);
3998         r->drivername           = talloc_strdup(mem_ctx, info2->drivername);
3999         W_ERROR_HAVE_NO_MEMORY(r->drivername);
4000
4001         if (info2->comment[0] == '\0') {
4002                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
4003         } else {
4004                 r->comment      = talloc_strdup(mem_ctx, info2->comment);
4005         }
4006         W_ERROR_HAVE_NO_MEMORY(r->comment);
4007
4008         r->location             = talloc_strdup(mem_ctx, info2->location);
4009         W_ERROR_HAVE_NO_MEMORY(r->location);
4010         r->sepfile              = talloc_strdup(mem_ctx, info2->sepfile);
4011         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4012         r->printprocessor       = talloc_strdup(mem_ctx, info2->printprocessor);
4013         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4014         r->datatype             = talloc_strdup(mem_ctx, info2->datatype);
4015         W_ERROR_HAVE_NO_MEMORY(r->datatype);
4016         r->parameters           = talloc_strdup(mem_ctx, info2->parameters);
4017         W_ERROR_HAVE_NO_MEMORY(r->parameters);
4018
4019         r->attributes           = info2->attributes;
4020
4021         r->priority             = info2->priority;
4022         r->defaultpriority      = info2->defaultpriority;
4023         r->starttime            = info2->starttime;
4024         r->untiltime            = info2->untiltime;
4025         r->status               = nt_printq_status(status.status);
4026         r->cjobs                = count;
4027         r->averageppm           = info2->averageppm;
4028
4029         copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4030         if (!r->devmode) {
4031                 DEBUG(8,("Returning NULL Devicemode!\n"));
4032         }
4033
4034         compose_devicemode_devicename(r->devmode, r->printername);
4035
4036         r->secdesc = NULL;
4037
4038         if (info2->secdesc != NULL) {
4039                 /* don't use talloc_steal() here unless you do a deep steal of all
4040                    the SEC_DESC members */
4041
4042                 r->secdesc      = dup_sec_desc(mem_ctx, info2->secdesc);
4043         }
4044
4045         return WERR_OK;
4046 }
4047
4048 /********************************************************************
4049  * construct_printer_info3
4050  * fill a spoolss_PrinterInfo3 struct
4051  ********************************************************************/
4052
4053 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4054                                       const struct spoolss_PrinterInfo2 *info2,
4055                                       const char *servername,
4056                                       struct spoolss_PrinterInfo3 *r,
4057                                       int snum)
4058 {
4059         /* These are the components of the SD we are returning. */
4060
4061         if (info2->secdesc != NULL) {
4062                 /* don't use talloc_steal() here unless you do a deep steal of all
4063                    the SEC_DESC members */
4064
4065                 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4066                 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
4067         }
4068
4069         return WERR_OK;
4070 }
4071
4072 /********************************************************************
4073  * construct_printer_info4
4074  * fill a spoolss_PrinterInfo4 struct
4075  ********************************************************************/
4076
4077 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4078                                       const struct spoolss_PrinterInfo2 *info2,
4079                                       const char *servername,
4080                                       struct spoolss_PrinterInfo4 *r,
4081                                       int snum)
4082 {
4083         WERROR result;
4084
4085         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4086         if (!W_ERROR_IS_OK(result)) {
4087                 return result;
4088         }
4089
4090         if (servername) {
4091                 r->servername   = talloc_strdup(mem_ctx, servername);
4092                 W_ERROR_HAVE_NO_MEMORY(r->servername);
4093         } else {
4094                 r->servername = NULL;
4095         }
4096
4097         r->attributes   = info2->attributes;
4098
4099         return WERR_OK;
4100 }
4101
4102 /********************************************************************
4103  * construct_printer_info5
4104  * fill a spoolss_PrinterInfo5 struct
4105  ********************************************************************/
4106
4107 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4108                                       const struct spoolss_PrinterInfo2 *info2,
4109                                       const char *servername,
4110                                       struct spoolss_PrinterInfo5 *r,
4111                                       int snum)
4112 {
4113         WERROR result;
4114
4115         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4116         if (!W_ERROR_IS_OK(result)) {
4117                 return result;
4118         }
4119
4120         r->portname     = talloc_strdup(mem_ctx, info2->portname);
4121         W_ERROR_HAVE_NO_MEMORY(r->portname);
4122
4123         r->attributes   = info2->attributes;
4124
4125         /* these two are not used by NT+ according to MSDN */
4126         r->device_not_selected_timeout          = 0x0;  /* have seen 0x3a98 */
4127         r->transmission_retry_timeout           = 0x0;  /* have seen 0xafc8 */
4128
4129         return WERR_OK;
4130 }
4131
4132 /********************************************************************
4133  * construct_printer_info_6
4134  * fill a spoolss_PrinterInfo6 struct
4135  ********************************************************************/
4136
4137 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4138                                       struct messaging_context *msg_ctx,
4139                                       const struct spoolss_PrinterInfo2 *info2,
4140                                       const char *servername,
4141                                       struct spoolss_PrinterInfo6 *r,
4142                                       int snum)
4143 {
4144         int count;
4145         print_status_struct status;
4146
4147         count = print_queue_length(msg_ctx, snum, &status);
4148
4149         r->status = nt_printq_status(status.status);
4150
4151         return WERR_OK;
4152 }
4153
4154 /********************************************************************
4155  * construct_printer_info7
4156  * fill a spoolss_PrinterInfo7 struct
4157  ********************************************************************/
4158
4159 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4160                                       struct messaging_context *msg_ctx,
4161                                       const char *servername,
4162                                       struct spoolss_PrinterInfo7 *r,
4163                                       int snum)
4164 {
4165         struct auth_serversupplied_info *session_info;
4166         struct GUID guid;
4167         NTSTATUS status;
4168
4169         status = make_session_info_system(mem_ctx, &session_info);
4170         if (!NT_STATUS_IS_OK(status)) {
4171                 DEBUG(0, ("construct_printer_info7: "
4172                           "Could not create system session_info\n"));
4173                 return WERR_NOMEM;
4174         }
4175
4176         if (is_printer_published(mem_ctx, session_info, msg_ctx,
4177                                  servername,
4178                                  lp_servicename(snum), &guid, NULL)) {
4179                 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4180                 r->action = DSPRINT_PUBLISH;
4181         } else {
4182                 r->guid = talloc_strdup(mem_ctx, "");
4183                 r->action = DSPRINT_UNPUBLISH;
4184         }
4185         W_ERROR_HAVE_NO_MEMORY(r->guid);
4186
4187         TALLOC_FREE(session_info);
4188         return WERR_OK;
4189 }
4190
4191 /********************************************************************
4192  * construct_printer_info8
4193  * fill a spoolss_PrinterInfo8 struct
4194  ********************************************************************/
4195
4196 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4197                                       const struct spoolss_PrinterInfo2 *info2,
4198                                       const char *servername,
4199                                       struct spoolss_DeviceModeInfo *r,
4200                                       int snum)
4201 {
4202         WERROR result;
4203         const char *printername;
4204
4205         result = create_printername(mem_ctx, servername, info2->printername, &printername);
4206         if (!W_ERROR_IS_OK(result)) {
4207                 return result;
4208         }
4209
4210         copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4211         if (!r->devmode) {
4212                 DEBUG(8,("Returning NULL Devicemode!\n"));
4213         }
4214
4215         compose_devicemode_devicename(r->devmode, printername);
4216
4217         return WERR_OK;
4218 }
4219
4220
4221 /********************************************************************
4222 ********************************************************************/
4223
4224 static bool snum_is_shared_printer(int snum)
4225 {
4226         return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4227 }
4228
4229 /********************************************************************
4230  Spoolss_enumprinters.
4231 ********************************************************************/
4232
4233 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4234                                            const struct auth_serversupplied_info *session_info,
4235                                            struct messaging_context *msg_ctx,
4236                                            const char *servername,
4237                                            uint32_t level,
4238                                            uint32_t flags,
4239                                            union spoolss_PrinterInfo **info_p,
4240                                            uint32_t *count_p)
4241 {
4242         int snum;
4243         int n_services = lp_numservices();
4244         union spoolss_PrinterInfo *info = NULL;
4245         uint32_t count = 0;
4246         WERROR result = WERR_OK;
4247
4248         *count_p = 0;
4249         *info_p = NULL;
4250
4251         for (snum = 0; snum < n_services; snum++) {
4252
4253                 const char *printer;
4254                 struct spoolss_PrinterInfo2 *info2;
4255
4256                 if (!snum_is_shared_printer(snum)) {
4257                         continue;
4258                 }
4259
4260                 printer = lp_const_servicename(snum);
4261
4262                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4263                         printer, snum));
4264
4265                 result = winreg_create_printer(mem_ctx,
4266                                                session_info,
4267                                                msg_ctx,
4268                                                printer);
4269                 if (!W_ERROR_IS_OK(result)) {
4270                         goto out;
4271                 }
4272
4273                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4274                                             union spoolss_PrinterInfo,
4275                                             count + 1);
4276                 if (!info) {
4277                         result = WERR_NOMEM;
4278                         goto out;
4279                 }
4280
4281                 result = winreg_get_printer(mem_ctx, session_info, msg_ctx,
4282                                             printer, &info2);
4283                 if (!W_ERROR_IS_OK(result)) {
4284                         goto out;
4285                 }
4286
4287                 switch (level) {
4288                 case 0:
4289                         result = construct_printer_info0(info, session_info,
4290                                                          msg_ctx, info2,
4291                                                          servername,
4292                                                          &info[count].info0, snum);
4293                         break;
4294                 case 1:
4295                         result = construct_printer_info1(info, info2, flags,
4296                                                          servername,
4297                                                          &info[count].info1, snum);
4298                         break;
4299                 case 2:
4300                         result = construct_printer_info2(info, msg_ctx, info2,
4301                                                          servername,
4302                                                          &info[count].info2, snum);
4303                         break;
4304                 case 4:
4305                         result = construct_printer_info4(info, info2,
4306                                                          servername,
4307                                                          &info[count].info4, snum);
4308                         break;
4309                 case 5:
4310                         result = construct_printer_info5(info, info2,
4311                                                          servername,
4312                                                          &info[count].info5, snum);
4313                         break;
4314
4315                 default:
4316                         result = WERR_UNKNOWN_LEVEL;
4317                         goto out;
4318                 }
4319
4320                 if (!W_ERROR_IS_OK(result)) {
4321                         goto out;
4322                 }
4323
4324                 count++;
4325         }
4326
4327         *count_p = count;
4328         *info_p = info;
4329
4330  out:
4331         if (!W_ERROR_IS_OK(result)) {
4332                 TALLOC_FREE(info);
4333                 return result;
4334         }
4335
4336         *info_p = info;
4337
4338         return WERR_OK;
4339 }
4340
4341 /********************************************************************
4342  * handle enumeration of printers at level 0
4343  ********************************************************************/
4344
4345 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4346                                   const struct auth_serversupplied_info *session_info,
4347                                   struct messaging_context *msg_ctx,
4348                                   uint32_t flags,
4349                                   const char *servername,
4350                                   union spoolss_PrinterInfo **info,
4351                                   uint32_t *count)
4352 {
4353         DEBUG(4,("enum_all_printers_info_0\n"));
4354
4355         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4356                                             servername, 0, flags, info, count);
4357 }
4358
4359
4360 /********************************************************************
4361 ********************************************************************/
4362
4363 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4364                                        const struct auth_serversupplied_info *session_info,
4365                                        struct messaging_context *msg_ctx,
4366                                        const char *servername,
4367                                        uint32_t flags,
4368                                        union spoolss_PrinterInfo **info,
4369                                        uint32_t *count)
4370 {
4371         DEBUG(4,("enum_all_printers_info_1\n"));
4372
4373         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4374                                             servername, 1, flags, info, count);
4375 }
4376
4377 /********************************************************************
4378  enum_all_printers_info_1_local.
4379 *********************************************************************/
4380
4381 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4382                                              const struct auth_serversupplied_info *session_info,
4383                                              struct messaging_context *msg_ctx,
4384                                              const char *servername,
4385                                              union spoolss_PrinterInfo **info,
4386                                              uint32_t *count)
4387 {
4388         DEBUG(4,("enum_all_printers_info_1_local\n"));
4389
4390         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4391                                         servername, PRINTER_ENUM_ICON8, info, count);
4392 }
4393
4394 /********************************************************************
4395  enum_all_printers_info_1_name.
4396 *********************************************************************/
4397
4398 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4399                                             const struct auth_serversupplied_info *session_info,
4400                                             struct messaging_context *msg_ctx,
4401                                             const char *servername,
4402                                             union spoolss_PrinterInfo **info,
4403                                             uint32_t *count)
4404 {
4405         const char *s = servername;
4406
4407         DEBUG(4,("enum_all_printers_info_1_name\n"));
4408
4409         if ((servername[0] == '\\') && (servername[1] == '\\')) {
4410                 s = servername + 2;
4411         }
4412
4413         if (!is_myname_or_ipaddr(s)) {
4414                 return WERR_INVALID_NAME;
4415         }
4416
4417         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4418                                         servername, PRINTER_ENUM_ICON8, info, count);
4419 }
4420
4421 /********************************************************************
4422  enum_all_printers_info_1_network.
4423 *********************************************************************/
4424
4425 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4426                                                const struct auth_serversupplied_info *session_info,
4427                                                struct messaging_context *msg_ctx,
4428                                                const char *servername,
4429                                                union spoolss_PrinterInfo **info,
4430                                                uint32_t *count)
4431 {
4432         const char *s = servername;
4433
4434         DEBUG(4,("enum_all_printers_info_1_network\n"));
4435
4436         /* If we respond to a enum_printers level 1 on our name with flags
4437            set to PRINTER_ENUM_REMOTE with a list of printers then these
4438            printers incorrectly appear in the APW browse list.
4439            Specifically the printers for the server appear at the workgroup
4440            level where all the other servers in the domain are
4441            listed. Windows responds to this call with a
4442            WERR_CAN_NOT_COMPLETE so we should do the same. */
4443
4444         if (servername[0] == '\\' && servername[1] == '\\') {
4445                  s = servername + 2;
4446         }
4447
4448         if (is_myname_or_ipaddr(s)) {
4449                  return WERR_CAN_NOT_COMPLETE;
4450         }
4451
4452         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4453                                         servername, PRINTER_ENUM_NAME, info, count);
4454 }
4455
4456 /********************************************************************
4457  * api_spoolss_enumprinters
4458  *
4459  * called from api_spoolss_enumprinters (see this to understand)
4460  ********************************************************************/
4461
4462 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4463                                        const struct auth_serversupplied_info *session_info,
4464                                        struct messaging_context *msg_ctx,
4465                                        const char *servername,
4466                                        union spoolss_PrinterInfo **info,
4467                                        uint32_t *count)
4468 {
4469         DEBUG(4,("enum_all_printers_info_2\n"));
4470
4471         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4472                                             servername, 2, 0, info, count);
4473 }
4474
4475 /********************************************************************
4476  * handle enumeration of printers at level 1
4477  ********************************************************************/
4478
4479 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4480                                   const struct auth_serversupplied_info *session_info,
4481                                   struct messaging_context *msg_ctx,
4482                                   uint32_t flags,
4483                                   const char *servername,
4484                                   union spoolss_PrinterInfo **info,
4485                                   uint32_t *count)
4486 {
4487         /* Not all the flags are equals */
4488
4489         if (flags & PRINTER_ENUM_LOCAL) {
4490                 return enum_all_printers_info_1_local(mem_ctx, session_info,
4491                                                       msg_ctx, servername, info, count);
4492         }
4493
4494         if (flags & PRINTER_ENUM_NAME) {
4495                 return enum_all_printers_info_1_name(mem_ctx, session_info,
4496                                                      msg_ctx, servername, info,
4497                                                      count);
4498         }
4499
4500         if (flags & PRINTER_ENUM_NETWORK) {
4501                 return enum_all_printers_info_1_network(mem_ctx, session_info,
4502                                                         msg_ctx, servername, info,
4503                                                         count);
4504         }
4505
4506         return WERR_OK; /* NT4sp5 does that */
4507 }
4508
4509 /********************************************************************
4510  * handle enumeration of printers at level 2
4511  ********************************************************************/
4512
4513 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4514                                   const struct auth_serversupplied_info *session_info,
4515                                   struct messaging_context *msg_ctx,
4516                                   uint32_t flags,
4517                                   const char *servername,
4518                                   union spoolss_PrinterInfo **info,
4519                                   uint32_t *count)
4520 {
4521         if (flags & PRINTER_ENUM_LOCAL) {
4522
4523                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4524                                                 servername,
4525                                                 info, count);
4526         }
4527
4528         if (flags & PRINTER_ENUM_NAME) {
4529                 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4530                         return WERR_INVALID_NAME;
4531                 }
4532
4533                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4534                                                 servername,
4535                                                 info, count);
4536         }
4537
4538         if (flags & PRINTER_ENUM_REMOTE) {
4539                 return WERR_UNKNOWN_LEVEL;
4540         }
4541
4542         return WERR_OK;
4543 }
4544
4545 /********************************************************************
4546  * handle enumeration of printers at level 4
4547  ********************************************************************/
4548
4549 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4550                                   const struct auth_serversupplied_info *session_info,
4551                                   struct messaging_context *msg_ctx,
4552                                   uint32_t flags,
4553                                   const char *servername,
4554                                   union spoolss_PrinterInfo **info,
4555                                   uint32_t *count)
4556 {
4557         DEBUG(4,("enum_all_printers_info_4\n"));
4558
4559         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4560                                             servername, 4, flags, info, count);
4561 }
4562
4563
4564 /********************************************************************
4565  * handle enumeration of printers at level 5
4566  ********************************************************************/
4567
4568 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4569                                   const struct auth_serversupplied_info *session_info,
4570                                   struct messaging_context *msg_ctx,
4571                                   uint32_t flags,
4572                                   const char *servername,
4573                                   union spoolss_PrinterInfo **info,
4574                                   uint32_t *count)
4575 {
4576         DEBUG(4,("enum_all_printers_info_5\n"));
4577
4578         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4579                                             servername, 5, flags, info, count);
4580 }
4581
4582 /****************************************************************
4583  _spoolss_EnumPrinters
4584 ****************************************************************/
4585
4586 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4587                              struct spoolss_EnumPrinters *r)
4588 {
4589         const struct auth_serversupplied_info *session_info = get_session_info_system();
4590         WERROR result;
4591
4592         /* that's an [in out] buffer */
4593
4594         if (!r->in.buffer && (r->in.offered != 0)) {
4595                 return WERR_INVALID_PARAM;
4596         }
4597
4598         DEBUG(4,("_spoolss_EnumPrinters\n"));
4599
4600         *r->out.needed = 0;
4601         *r->out.count = 0;
4602         *r->out.info = NULL;
4603
4604         /*
4605          * Level 1:
4606          *          flags==PRINTER_ENUM_NAME
4607          *           if name=="" then enumerates all printers
4608          *           if name!="" then enumerate the printer
4609          *          flags==PRINTER_ENUM_REMOTE
4610          *          name is NULL, enumerate printers
4611          * Level 2: name!="" enumerates printers, name can't be NULL
4612          * Level 3: doesn't exist
4613          * Level 4: does a local registry lookup
4614          * Level 5: same as Level 2
4615          */
4616
4617         if (r->in.server && r->in.server[0] == '\0') {
4618                 r->in.server = NULL;
4619         }
4620
4621         switch (r->in.level) {
4622         case 0:
4623                 result = enumprinters_level0(p->mem_ctx, session_info,
4624                                              p->msg_ctx, r->in.flags,
4625                                              r->in.server,
4626                                              r->out.info, r->out.count);
4627                 break;
4628         case 1:
4629                 result = enumprinters_level1(p->mem_ctx, session_info,
4630                                              p->msg_ctx, r->in.flags,
4631                                              r->in.server,
4632                                              r->out.info, r->out.count);
4633                 break;
4634         case 2:
4635                 result = enumprinters_level2(p->mem_ctx, session_info,
4636                                              p->msg_ctx, r->in.flags,
4637                                              r->in.server,
4638                                              r->out.info, r->out.count);
4639                 break;
4640         case 4:
4641                 result = enumprinters_level4(p->mem_ctx, session_info,
4642                                              p->msg_ctx, r->in.flags,
4643                                              r->in.server,
4644                                              r->out.info, r->out.count);
4645                 break;
4646         case 5:
4647                 result = enumprinters_level5(p->mem_ctx, session_info,
4648                                              p->msg_ctx, r->in.flags,
4649                                              r->in.server,
4650                                              r->out.info, r->out.count);
4651                 break;
4652         default:
4653                 return WERR_UNKNOWN_LEVEL;
4654         }
4655
4656         if (!W_ERROR_IS_OK(result)) {
4657                 return result;
4658         }
4659
4660         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4661                                                      spoolss_EnumPrinters,
4662                                                      *r->out.info, r->in.level,
4663                                                      *r->out.count);
4664         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4665         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4666
4667         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4668 }
4669
4670 /****************************************************************
4671  _spoolss_GetPrinter
4672 ****************************************************************/
4673
4674 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4675                            struct spoolss_GetPrinter *r)
4676 {
4677         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4678         struct spoolss_PrinterInfo2 *info2 = NULL;
4679         WERROR result = WERR_OK;
4680         int snum;
4681
4682         /* that's an [in out] buffer */
4683
4684         if (!r->in.buffer && (r->in.offered != 0)) {
4685                 return WERR_INVALID_PARAM;
4686         }
4687
4688         *r->out.needed = 0;
4689
4690         if (Printer == NULL) {
4691                 return WERR_BADFID;
4692         }
4693
4694         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4695                 return WERR_BADFID;
4696         }
4697
4698         result = winreg_get_printer(p->mem_ctx,
4699                                     get_session_info_system(),
4700                                     p->msg_ctx,
4701                                     lp_const_servicename(snum),
4702                                     &info2);
4703         if (!W_ERROR_IS_OK(result)) {
4704                 goto out;
4705         }
4706
4707         switch (r->in.level) {
4708         case 0:
4709                 result = construct_printer_info0(p->mem_ctx,
4710                                                  get_session_info_system(),
4711                                                  p->msg_ctx,
4712                                                  info2,
4713                                                  Printer->servername,
4714                                                  &r->out.info->info0,
4715                                                  snum);
4716                 break;
4717         case 1:
4718                 result = construct_printer_info1(p->mem_ctx, info2,
4719                                                  PRINTER_ENUM_ICON8,
4720                                                  Printer->servername,
4721                                                  &r->out.info->info1, snum);
4722                 break;
4723         case 2:
4724                 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4725                                                  Printer->servername,
4726                                                  &r->out.info->info2, snum);
4727                 break;
4728         case 3:
4729                 result = construct_printer_info3(p->mem_ctx, info2,
4730                                                  Printer->servername,
4731                                                  &r->out.info->info3, snum);
4732                 break;
4733         case 4:
4734                 result = construct_printer_info4(p->mem_ctx, info2,
4735                                                  Printer->servername,
4736                                                  &r->out.info->info4, snum);
4737                 break;
4738         case 5:
4739                 result = construct_printer_info5(p->mem_ctx, info2,
4740                                                  Printer->servername,
4741                                                  &r->out.info->info5, snum);
4742                 break;
4743         case 6:
4744                 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4745                                                  Printer->servername,
4746                                                  &r->out.info->info6, snum);
4747                 break;
4748         case 7:
4749                 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4750                                                  Printer->servername,
4751                                                  &r->out.info->info7, snum);
4752                 break;
4753         case 8:
4754                 result = construct_printer_info8(p->mem_ctx, info2,
4755                                                  Printer->servername,
4756                                                  &r->out.info->info8, snum);
4757                 break;
4758         default:
4759                 result = WERR_UNKNOWN_LEVEL;
4760                 break;
4761         }
4762
4763  out:
4764         if (!W_ERROR_IS_OK(result)) {
4765                 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4766                           r->in.level, win_errstr(result)));
4767                 TALLOC_FREE(r->out.info);
4768                 return result;
4769         }
4770
4771         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4772                                                r->out.info, r->in.level);
4773         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4774
4775         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4776 }
4777
4778 /********************************************************************
4779  ********************************************************************/
4780
4781 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4782         do { \
4783                 if (in && strlen(in)) { \
4784                         out = talloc_strdup(mem_ctx, in); \
4785                 } else { \
4786                         out = talloc_strdup(mem_ctx, ""); \
4787                 } \
4788                 W_ERROR_HAVE_NO_MEMORY(out); \
4789         } while (0);
4790
4791 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4792         do { \
4793                 if (in && strlen(in)) { \
4794                         out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4795                 } else { \
4796                         out = talloc_strdup(mem_ctx, ""); \
4797                 } \
4798                 W_ERROR_HAVE_NO_MEMORY(out); \
4799         } while (0);
4800
4801 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4802                                                   const char **string_array,
4803                                                   const char ***presult,
4804                                                   const char *cservername,
4805                                                   const char *arch,
4806                                                   int version)
4807 {
4808         int i, num_strings = 0;
4809         const char **array = NULL;
4810
4811         if (string_array == NULL) {
4812                 return WERR_INVALID_PARAMETER;
4813         }
4814
4815         for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4816                 const char *str = NULL;
4817
4818                 if (cservername == NULL || arch == NULL) {
4819                         FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4820                 } else {
4821                         FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4822                 }
4823
4824                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4825                         TALLOC_FREE(array);
4826                         return WERR_NOMEM;
4827                 }
4828         }
4829
4830         if (i > 0) {
4831                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4832                              &array, &num_strings);
4833         }
4834
4835         if (presult) {
4836                 *presult = array;
4837         }
4838
4839         return WERR_OK;
4840 }
4841
4842 /********************************************************************
4843  * fill a spoolss_DriverInfo1 struct
4844  ********************************************************************/
4845
4846 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4847                                         struct spoolss_DriverInfo1 *r,
4848                                         const struct spoolss_DriverInfo8 *driver,
4849                                         const char *servername)
4850 {
4851         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4852         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4853
4854         return WERR_OK;
4855 }
4856
4857 /********************************************************************
4858  * fill a spoolss_DriverInfo2 struct
4859  ********************************************************************/
4860
4861 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4862                                         struct spoolss_DriverInfo2 *r,
4863                                         const struct spoolss_DriverInfo8 *driver,
4864                                         const char *servername)
4865
4866 {
4867         const char *cservername = canon_servername(servername);
4868
4869         r->version              = driver->version;
4870
4871         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4872         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4873         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4874         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4875
4876         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4877                                driver->architecture,
4878                                driver->version,
4879                                driver->driver_path,
4880                                r->driver_path);
4881
4882         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4883                                driver->architecture,
4884                                driver->version,
4885                                driver->data_file,
4886                                r->data_file);
4887
4888         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4889                                driver->architecture,
4890                                driver->version,
4891                                driver->config_file,
4892                                r->config_file);
4893
4894         return WERR_OK;
4895 }
4896
4897 /********************************************************************
4898  * fill a spoolss_DriverInfo3 struct
4899  ********************************************************************/
4900
4901 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4902                                         struct spoolss_DriverInfo3 *r,
4903                                         const struct spoolss_DriverInfo8 *driver,
4904                                         const char *servername)
4905 {
4906         const char *cservername = canon_servername(servername);
4907
4908         r->version              = driver->version;
4909
4910         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4911         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4912         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4913         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4914
4915         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4916                                driver->architecture,
4917                                driver->version,
4918                                driver->driver_path,
4919                                r->driver_path);
4920
4921         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4922                                driver->architecture,
4923                                driver->version,
4924                                driver->data_file,
4925                                r->data_file);
4926
4927         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4928                                driver->architecture,
4929                                driver->version,
4930                                driver->config_file,
4931                                r->config_file);
4932
4933         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4934                                driver->architecture,
4935                                driver->version,
4936                                driver->help_file,
4937                                r->help_file);
4938
4939         FILL_DRIVER_STRING(mem_ctx,
4940                            driver->monitor_name,
4941                            r->monitor_name);
4942
4943         FILL_DRIVER_STRING(mem_ctx,
4944                            driver->default_datatype,
4945                            r->default_datatype);
4946
4947         return string_array_from_driver_info(mem_ctx,
4948                                              driver->dependent_files,
4949                                              &r->dependent_files,
4950                                              cservername,
4951                                              driver->architecture,
4952                                              driver->version);
4953 }
4954
4955 /********************************************************************
4956  * fill a spoolss_DriverInfo4 struct
4957  ********************************************************************/
4958
4959 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4960                                         struct spoolss_DriverInfo4 *r,
4961                                         const struct spoolss_DriverInfo8 *driver,
4962                                         const char *servername)
4963 {
4964         const char *cservername = canon_servername(servername);
4965         WERROR result;
4966
4967         r->version              = driver->version;
4968
4969         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4970         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4971         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4972         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4973
4974         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4975                                driver->architecture,
4976                                driver->version,
4977                                driver->driver_path,
4978                                r->driver_path);
4979
4980         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4981                                driver->architecture,
4982                                driver->version,
4983                                driver->data_file,
4984                                r->data_file);
4985
4986         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4987                                driver->architecture,
4988                                driver->version,
4989                                driver->config_file,
4990                                r->config_file);
4991
4992         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4993                                driver->architecture,
4994                                driver->version,
4995                                driver->help_file,
4996                                r->help_file);
4997
4998         result = string_array_from_driver_info(mem_ctx,
4999                                                driver->dependent_files,
5000                                                &r->dependent_files,
5001                                                cservername,
5002                                                driver->architecture,
5003                                                driver->version);
5004         if (!W_ERROR_IS_OK(result)) {
5005                 return result;
5006         }
5007
5008         FILL_DRIVER_STRING(mem_ctx,
5009                            driver->monitor_name,
5010                            r->monitor_name);
5011
5012         FILL_DRIVER_STRING(mem_ctx,
5013                            driver->default_datatype,
5014                            r->default_datatype);
5015
5016
5017         result = string_array_from_driver_info(mem_ctx,
5018                                                driver->previous_names,
5019                                                &r->previous_names,
5020                                                NULL, NULL, 0);
5021
5022         return result;
5023 }
5024
5025 /********************************************************************
5026  * fill a spoolss_DriverInfo5 struct
5027  ********************************************************************/
5028
5029 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5030                                         struct spoolss_DriverInfo5 *r,
5031                                         const struct spoolss_DriverInfo8 *driver,
5032                                         const char *servername)
5033 {
5034         const char *cservername = canon_servername(servername);
5035
5036         r->version              = driver->version;
5037
5038         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5039         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5040         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5041         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5042
5043         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5044                                driver->architecture,
5045                                driver->version,
5046                                driver->driver_path,
5047                                r->driver_path);
5048
5049         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5050                                driver->architecture,
5051                                driver->version,
5052                                driver->data_file,
5053                                r->data_file);
5054
5055         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5056                                driver->architecture,
5057                                driver->version,
5058                                driver->config_file,
5059                                r->config_file);
5060
5061         r->driver_attributes    = 0;
5062         r->config_version       = 0;
5063         r->driver_version       = 0;
5064
5065         return WERR_OK;
5066 }
5067 /********************************************************************
5068  * fill a spoolss_DriverInfo6 struct
5069  ********************************************************************/
5070
5071 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5072                                         struct spoolss_DriverInfo6 *r,
5073                                         const struct spoolss_DriverInfo8 *driver,
5074                                         const char *servername)
5075 {
5076         const char *cservername = canon_servername(servername);
5077         WERROR result;
5078
5079         r->version              = driver->version;
5080
5081         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5082         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5083         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5084         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5085
5086         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5087                                driver->architecture,
5088                                driver->version,
5089                                driver->driver_path,
5090                                r->driver_path);
5091
5092         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5093                                driver->architecture,
5094                                driver->version,
5095                                driver->data_file,
5096                                r->data_file);
5097
5098         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5099                                driver->architecture,
5100                                driver->version,
5101                                driver->config_file,
5102                                r->config_file);
5103
5104         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5105                                driver->architecture,
5106                                driver->version,
5107                                driver->help_file,
5108                                r->help_file);
5109
5110         FILL_DRIVER_STRING(mem_ctx,
5111                            driver->monitor_name,
5112                            r->monitor_name);
5113
5114         FILL_DRIVER_STRING(mem_ctx,
5115                            driver->default_datatype,
5116                            r->default_datatype);
5117
5118         result = string_array_from_driver_info(mem_ctx,
5119                                                driver->dependent_files,
5120                                                &r->dependent_files,
5121                                                cservername,
5122                                                driver->architecture,
5123                                                driver->version);
5124         if (!W_ERROR_IS_OK(result)) {
5125                 return result;
5126         }
5127
5128         result = string_array_from_driver_info(mem_ctx,
5129                                                driver->previous_names,
5130                                                &r->previous_names,
5131                                                NULL, NULL, 0);
5132         if (!W_ERROR_IS_OK(result)) {
5133                 return result;
5134         }
5135
5136         r->driver_date          = driver->driver_date;
5137         r->driver_version       = driver->driver_version;
5138
5139         FILL_DRIVER_STRING(mem_ctx,
5140                            driver->manufacturer_name,
5141                            r->manufacturer_name);
5142         FILL_DRIVER_STRING(mem_ctx,
5143                            driver->manufacturer_url,
5144                            r->manufacturer_url);
5145         FILL_DRIVER_STRING(mem_ctx,
5146                            driver->hardware_id,
5147                            r->hardware_id);
5148         FILL_DRIVER_STRING(mem_ctx,
5149                            driver->provider,
5150                            r->provider);
5151
5152         return WERR_OK;
5153 }
5154
5155 /********************************************************************
5156  * fill a spoolss_DriverInfo8 struct
5157  ********************************************************************/
5158
5159 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5160                                         struct spoolss_DriverInfo8 *r,
5161                                         const struct spoolss_DriverInfo8 *driver,
5162                                         const char *servername)
5163 {
5164         const char *cservername = canon_servername(servername);
5165         WERROR result;
5166
5167         r->version              = driver->version;
5168
5169         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5170         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5171         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5172         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5173
5174         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5175                                driver->architecture,
5176                                driver->version,
5177                                driver->driver_path,
5178                                r->driver_path);
5179
5180         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5181                                driver->architecture,
5182                                driver->version,
5183                                driver->data_file,
5184                                r->data_file);
5185
5186         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5187                                driver->architecture,
5188                                driver->version,
5189                                driver->config_file,
5190                                r->config_file);
5191
5192         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5193                                driver->architecture,
5194                                driver->version,
5195                                driver->help_file,
5196                                r->help_file);
5197
5198         FILL_DRIVER_STRING(mem_ctx,
5199                            driver->monitor_name,
5200                            r->monitor_name);
5201
5202         FILL_DRIVER_STRING(mem_ctx,
5203                            driver->default_datatype,
5204                            r->default_datatype);
5205
5206         result = string_array_from_driver_info(mem_ctx,
5207                                                driver->dependent_files,
5208                                                &r->dependent_files,
5209                                                cservername,
5210                                                driver->architecture,
5211                                                driver->version);
5212         if (!W_ERROR_IS_OK(result)) {
5213                 return result;
5214         }
5215
5216         result = string_array_from_driver_info(mem_ctx,
5217                                                driver->previous_names,
5218                                                &r->previous_names,
5219                                                NULL, NULL, 0);
5220         if (!W_ERROR_IS_OK(result)) {
5221                 return result;
5222         }
5223
5224         r->driver_date          = driver->driver_date;
5225         r->driver_version       = driver->driver_version;
5226
5227         FILL_DRIVER_STRING(mem_ctx,
5228                            driver->manufacturer_name,
5229                            r->manufacturer_name);
5230         FILL_DRIVER_STRING(mem_ctx,
5231                            driver->manufacturer_url,
5232                            r->manufacturer_url);
5233         FILL_DRIVER_STRING(mem_ctx,
5234                            driver->hardware_id,
5235                            r->hardware_id);
5236         FILL_DRIVER_STRING(mem_ctx,
5237                            driver->provider,
5238                            r->provider);
5239
5240         FILL_DRIVER_STRING(mem_ctx,
5241                            driver->print_processor,
5242                            r->print_processor);
5243         FILL_DRIVER_STRING(mem_ctx,
5244                            driver->vendor_setup,
5245                            r->vendor_setup);
5246
5247         result = string_array_from_driver_info(mem_ctx,
5248                                                driver->color_profiles,
5249                                                &r->color_profiles,
5250                                                NULL, NULL, 0);
5251         if (!W_ERROR_IS_OK(result)) {
5252                 return result;
5253         }
5254
5255         FILL_DRIVER_STRING(mem_ctx,
5256                            driver->inf_path,
5257                            r->inf_path);
5258
5259         r->printer_driver_attributes    = driver->printer_driver_attributes;
5260
5261         result = string_array_from_driver_info(mem_ctx,
5262                                                driver->core_driver_dependencies,
5263                                                &r->core_driver_dependencies,
5264                                                NULL, NULL, 0);
5265         if (!W_ERROR_IS_OK(result)) {
5266                 return result;
5267         }
5268
5269         r->min_inbox_driver_ver_date    = driver->min_inbox_driver_ver_date;
5270         r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5271
5272         return WERR_OK;
5273 }
5274
5275 #if 0 /* disabled until marshalling issues are resolved - gd */
5276 /********************************************************************
5277  ********************************************************************/
5278
5279 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5280                                           struct spoolss_DriverFileInfo *r,
5281                                           const char *cservername,
5282                                           const char *file_name,
5283                                           enum spoolss_DriverFileType file_type,
5284                                           uint32_t file_version)
5285 {
5286         r->file_name    = talloc_asprintf(mem_ctx, "\\\\%s%s",
5287                                           cservername, file_name);
5288         W_ERROR_HAVE_NO_MEMORY(r->file_name);
5289         r->file_type    = file_type;
5290         r->file_version = file_version;
5291
5292         return WERR_OK;
5293 }
5294
5295 /********************************************************************
5296  ********************************************************************/
5297
5298 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5299                                                  const struct spoolss_DriverInfo8 *driver,
5300                                                  const char *cservername,
5301                                                  struct spoolss_DriverFileInfo **info_p,
5302                                                  uint32_t *count_p)
5303 {
5304         struct spoolss_DriverFileInfo *info = NULL;
5305         uint32_t count = 0;
5306         WERROR result;
5307         uint32_t i;
5308
5309         *info_p = NULL;
5310         *count_p = 0;
5311
5312         if (strlen(driver->driver_path)) {
5313                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5314                                             struct spoolss_DriverFileInfo,
5315                                             count + 1);
5316                 W_ERROR_HAVE_NO_MEMORY(info);
5317                 result = fill_spoolss_DriverFileInfo(info,
5318                                                      &info[count],
5319                                                      cservername,
5320                                                      driver->driver_path,
5321                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5322                                                      0);
5323                 W_ERROR_NOT_OK_RETURN(result);
5324                 count++;
5325         }
5326
5327         if (strlen(driver->config_file)) {
5328                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5329                                             struct spoolss_DriverFileInfo,
5330                                             count + 1);
5331                 W_ERROR_HAVE_NO_MEMORY(info);
5332                 result = fill_spoolss_DriverFileInfo(info,
5333                                                      &info[count],
5334                                                      cservername,
5335                                                      driver->config_file,
5336                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5337                                                      0);
5338                 W_ERROR_NOT_OK_RETURN(result);
5339                 count++;
5340         }
5341
5342         if (strlen(driver->data_file)) {
5343                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5344                                             struct spoolss_DriverFileInfo,
5345                                             count + 1);
5346                 W_ERROR_HAVE_NO_MEMORY(info);
5347                 result = fill_spoolss_DriverFileInfo(info,
5348                                                      &info[count],
5349                                                      cservername,
5350                                                      driver->data_file,
5351                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
5352                                                      0);
5353                 W_ERROR_NOT_OK_RETURN(result);
5354                 count++;
5355         }
5356
5357         if (strlen(driver->help_file)) {
5358                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5359                                             struct spoolss_DriverFileInfo,
5360                                             count + 1);
5361                 W_ERROR_HAVE_NO_MEMORY(info);
5362                 result = fill_spoolss_DriverFileInfo(info,
5363                                                      &info[count],
5364                                                      cservername,
5365                                                      driver->help_file,
5366                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
5367                                                      0);
5368                 W_ERROR_NOT_OK_RETURN(result);
5369                 count++;
5370         }
5371
5372         for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5373                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5374                                             struct spoolss_DriverFileInfo,
5375                                             count + 1);
5376                 W_ERROR_HAVE_NO_MEMORY(info);
5377                 result = fill_spoolss_DriverFileInfo(info,
5378                                                      &info[count],
5379                                                      cservername,
5380                                                      driver->dependent_files[i],
5381                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5382                                                      0);
5383                 W_ERROR_NOT_OK_RETURN(result);
5384                 count++;
5385         }
5386
5387         *info_p = info;
5388         *count_p = count;
5389
5390         return WERR_OK;
5391 }
5392
5393 /********************************************************************
5394  * fill a spoolss_DriverInfo101 struct
5395  ********************************************************************/
5396
5397 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5398                                           struct spoolss_DriverInfo101 *r,
5399                                           const struct spoolss_DriverInfo8 *driver,
5400                                           const char *servername)
5401 {
5402         const char *cservername = canon_servername(servername);
5403         WERROR result;
5404
5405         r->version              = driver->version;
5406
5407         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5408         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5409         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5410         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5411
5412         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5413                                                     cservername,
5414                                                     &r->file_info,
5415                                                     &r->file_count);
5416         if (!W_ERROR_IS_OK(result)) {
5417                 return result;
5418         }
5419
5420         FILL_DRIVER_STRING(mem_ctx,
5421                            driver->monitor_name,
5422                            r->monitor_name);
5423
5424         FILL_DRIVER_STRING(mem_ctx,
5425                            driver->default_datatype,
5426                            r->default_datatype);
5427
5428         result = string_array_from_driver_info(mem_ctx,
5429                                                driver->previous_names,
5430                                                &r->previous_names,
5431                                                NULL, NULL, 0);
5432         if (!W_ERROR_IS_OK(result)) {
5433                 return result;
5434         }
5435
5436         r->driver_date          = driver->driver_date;
5437         r->driver_version       = driver->driver_version;
5438
5439         FILL_DRIVER_STRING(mem_ctx,
5440                            driver->manufacturer_name,
5441                            r->manufacturer_name);
5442         FILL_DRIVER_STRING(mem_ctx,
5443                            driver->manufacturer_url,
5444                            r->manufacturer_url);
5445         FILL_DRIVER_STRING(mem_ctx,
5446                            driver->hardware_id,
5447                            r->hardware_id);
5448         FILL_DRIVER_STRING(mem_ctx,
5449                            driver->provider,
5450                            r->provider);
5451
5452         return WERR_OK;
5453 }
5454 #endif
5455 /********************************************************************
5456  ********************************************************************/
5457
5458 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5459                                                   const struct auth_serversupplied_info *session_info,
5460                                                   struct messaging_context *msg_ctx,
5461                                                   uint32_t level,
5462                                                   union spoolss_DriverInfo *r,
5463                                                   int snum,
5464                                                   const char *servername,
5465                                                   const char *architecture,
5466                                                   uint32_t version)
5467 {
5468         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5469         struct spoolss_DriverInfo8 *driver;
5470         WERROR result;
5471
5472         if (level == 101) {
5473                 return WERR_UNKNOWN_LEVEL;
5474         }
5475
5476         result = winreg_get_printer(mem_ctx,
5477                                     session_info,
5478                                     msg_ctx,
5479                                     lp_const_servicename(snum),
5480                                     &pinfo2);
5481
5482         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5483                 win_errstr(result)));
5484
5485         if (!W_ERROR_IS_OK(result)) {
5486                 return WERR_INVALID_PRINTER_NAME;
5487         }
5488
5489         result = winreg_get_driver(mem_ctx, session_info, msg_ctx,
5490                                    architecture,
5491                                    pinfo2->drivername, version, &driver);
5492
5493         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5494                 win_errstr(result)));
5495
5496         if (!W_ERROR_IS_OK(result)) {
5497                 /*
5498                  * Is this a W2k client ?
5499                  */
5500
5501                 if (version < 3) {
5502                         talloc_free(pinfo2);
5503                         return WERR_UNKNOWN_PRINTER_DRIVER;
5504                 }
5505
5506                 /* Yes - try again with a WinNT driver. */
5507                 version = 2;
5508                 result = winreg_get_driver(mem_ctx, session_info, msg_ctx,
5509                                            architecture,
5510                                            pinfo2->drivername,
5511                                            version, &driver);
5512                 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5513                         win_errstr(result)));
5514                 if (!W_ERROR_IS_OK(result)) {
5515                         talloc_free(pinfo2);
5516                         return WERR_UNKNOWN_PRINTER_DRIVER;
5517                 }
5518         }
5519
5520         switch (level) {
5521         case 1:
5522                 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5523                 break;
5524         case 2:
5525                 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5526                 break;
5527         case 3:
5528                 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5529                 break;
5530         case 4:
5531                 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5532                 break;
5533         case 5:
5534                 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5535                 break;
5536         case 6:
5537                 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5538                 break;
5539         case 8:
5540                 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5541                 break;
5542 #if 0 /* disabled until marshalling issues are resolved - gd */
5543         case 101:
5544                 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5545                 break;
5546 #endif
5547         default:
5548                 result = WERR_UNKNOWN_LEVEL;
5549                 break;
5550         }
5551
5552         talloc_free(pinfo2);
5553         talloc_free(driver);
5554
5555         return result;
5556 }
5557
5558 /****************************************************************
5559  _spoolss_GetPrinterDriver2
5560 ****************************************************************/
5561
5562 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5563                                   struct spoolss_GetPrinterDriver2 *r)
5564 {
5565         struct printer_handle *printer;
5566         WERROR result;
5567
5568         int snum;
5569
5570         /* that's an [in out] buffer */
5571
5572         if (!r->in.buffer && (r->in.offered != 0)) {
5573                 return WERR_INVALID_PARAM;
5574         }
5575
5576         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5577
5578         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5579                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5580                 return WERR_INVALID_PRINTER_NAME;
5581         }
5582
5583         *r->out.needed = 0;
5584         *r->out.server_major_version = 0;
5585         *r->out.server_minor_version = 0;
5586
5587         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5588                 return WERR_BADFID;
5589         }
5590
5591         result = construct_printer_driver_info_level(p->mem_ctx,
5592                                                      get_session_info_system(),
5593                                                      p->msg_ctx,
5594                                                      r->in.level, r->out.info,
5595                                                      snum, printer->servername,
5596                                                      r->in.architecture,
5597                                                      r->in.client_major_version);
5598         if (!W_ERROR_IS_OK(result)) {
5599                 TALLOC_FREE(r->out.info);
5600                 return result;
5601         }
5602
5603         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5604                                                r->out.info, r->in.level);
5605         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5606
5607         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5608 }
5609
5610
5611 /****************************************************************
5612  _spoolss_StartPagePrinter
5613 ****************************************************************/
5614
5615 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5616                                  struct spoolss_StartPagePrinter *r)
5617 {
5618         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5619
5620         if (!Printer) {
5621                 DEBUG(3,("_spoolss_StartPagePrinter: "
5622                         "Error in startpageprinter printer handle\n"));
5623                 return WERR_BADFID;
5624         }
5625
5626         Printer->page_started = true;
5627         return WERR_OK;
5628 }
5629
5630 /****************************************************************
5631  _spoolss_EndPagePrinter
5632 ****************************************************************/
5633
5634 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5635                                struct spoolss_EndPagePrinter *r)
5636 {
5637         int snum;
5638
5639         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5640
5641         if (!Printer) {
5642                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5643                         OUR_HANDLE(r->in.handle)));
5644                 return WERR_BADFID;
5645         }
5646
5647         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5648                 return WERR_BADFID;
5649
5650         Printer->page_started = false;
5651         print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5652
5653         return WERR_OK;
5654 }
5655
5656 /****************************************************************
5657  _spoolss_StartDocPrinter
5658 ****************************************************************/
5659
5660 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5661                                 struct spoolss_StartDocPrinter *r)
5662 {
5663         struct spoolss_DocumentInfo1 *info_1;
5664         int snum;
5665         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5666         WERROR werr;
5667
5668         if (!Printer) {
5669                 DEBUG(2,("_spoolss_StartDocPrinter: "
5670                         "Invalid handle (%s:%u:%u)\n",
5671                         OUR_HANDLE(r->in.handle)));
5672                 return WERR_BADFID;
5673         }
5674
5675         if (Printer->jobid) {
5676                 DEBUG(2, ("_spoolss_StartDocPrinter: "
5677                           "StartDocPrinter called twice! "
5678                           "(existing jobid = %d)\n", Printer->jobid));
5679                 return WERR_INVALID_HANDLE;
5680         }
5681
5682         if (r->in.level != 1) {
5683                 return WERR_UNKNOWN_LEVEL;
5684         }
5685
5686         info_1 = r->in.info.info1;
5687
5688         /*
5689          * a nice thing with NT is it doesn't listen to what you tell it.
5690          * when asked to send _only_ RAW datas, it tries to send datas
5691          * in EMF format.
5692          *
5693          * So I add checks like in NT Server ...
5694          */
5695
5696         if (info_1->datatype) {
5697                 if (strcmp(info_1->datatype, "RAW") != 0) {
5698                         *r->out.job_id = 0;
5699                         return WERR_INVALID_DATATYPE;
5700                 }
5701         }
5702
5703         /* get the share number of the printer */
5704         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5705                 return WERR_BADFID;
5706         }
5707
5708         werr = print_job_start(p->session_info,
5709                                p->msg_ctx,
5710                                p->client_id->name,
5711                                snum,
5712                                info_1->document_name,
5713                                info_1->output_file,
5714                                Printer->devmode,
5715                                &Printer->jobid);
5716
5717         /* An error occured in print_job_start() so return an appropriate
5718            NT error code. */
5719
5720         if (!W_ERROR_IS_OK(werr)) {
5721                 return werr;
5722         }
5723
5724         Printer->document_started = true;
5725         *r->out.job_id = Printer->jobid;
5726
5727         return WERR_OK;
5728 }
5729
5730 /****************************************************************
5731  _spoolss_EndDocPrinter
5732 ****************************************************************/
5733
5734 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5735                               struct spoolss_EndDocPrinter *r)
5736 {
5737         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5738         NTSTATUS status;
5739         int snum;
5740
5741         if (!Printer) {
5742                 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5743                         OUR_HANDLE(r->in.handle)));
5744                 return WERR_BADFID;
5745         }
5746
5747         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5748                 return WERR_BADFID;
5749         }
5750
5751         Printer->document_started = false;
5752         status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5753         if (!NT_STATUS_IS_OK(status)) {
5754                 DEBUG(2, ("_spoolss_EndDocPrinter: "
5755                           "print_job_end failed [%s]\n",
5756                           nt_errstr(status)));
5757         }
5758
5759         Printer->jobid = 0;
5760         return ntstatus_to_werror(status);
5761 }
5762
5763 /****************************************************************
5764  _spoolss_WritePrinter
5765 ****************************************************************/
5766
5767 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5768                              struct spoolss_WritePrinter *r)
5769 {
5770         ssize_t buffer_written;
5771         int snum;
5772         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5773
5774         if (!Printer) {
5775                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5776                         OUR_HANDLE(r->in.handle)));
5777                 *r->out.num_written = r->in._data_size;
5778                 return WERR_BADFID;
5779         }
5780
5781         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5782                 return WERR_BADFID;
5783
5784         /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5785         buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5786                                                    snum, Printer->jobid,
5787                                                    (const char *)r->in.data.data,
5788                                                    (size_t)r->in._data_size);
5789         if (buffer_written == (ssize_t)-1) {
5790                 *r->out.num_written = 0;
5791                 if (errno == ENOSPC)
5792                         return WERR_NO_SPOOL_SPACE;
5793                 else
5794                         return WERR_ACCESS_DENIED;
5795         }
5796
5797         *r->out.num_written = r->in._data_size;
5798
5799         return WERR_OK;
5800 }
5801
5802 /********************************************************************
5803  * api_spoolss_getprinter
5804  * called from the spoolss dispatcher
5805  *
5806  ********************************************************************/
5807
5808 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5809                               struct pipes_struct *p)
5810 {
5811         const struct auth_serversupplied_info *session_info = p->session_info;
5812         int snum;
5813         WERROR errcode = WERR_BADFUNC;
5814         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5815
5816         if (!Printer) {
5817                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5818                         OUR_HANDLE(handle)));
5819                 return WERR_BADFID;
5820         }
5821
5822         if (!get_printer_snum(p, handle, &snum, NULL))
5823                 return WERR_BADFID;
5824
5825         switch (command) {
5826         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5827                 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
5828                 break;
5829         case SPOOLSS_PRINTER_CONTROL_RESUME:
5830         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5831                 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
5832                 break;
5833         case SPOOLSS_PRINTER_CONTROL_PURGE:
5834                 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
5835                 break;
5836         default:
5837                 return WERR_UNKNOWN_LEVEL;
5838         }
5839
5840         return errcode;
5841 }
5842
5843
5844 /****************************************************************
5845  _spoolss_AbortPrinter
5846  * From MSDN: "Deletes printer's spool file if printer is configured
5847  * for spooling"
5848 ****************************************************************/
5849
5850 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
5851                              struct spoolss_AbortPrinter *r)
5852 {
5853         struct printer_handle   *Printer = find_printer_index_by_hnd(p, r->in.handle);
5854         int             snum;
5855         WERROR          errcode = WERR_OK;
5856
5857         if (!Printer) {
5858                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5859                         OUR_HANDLE(r->in.handle)));
5860                 return WERR_BADFID;
5861         }
5862
5863         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5864                 return WERR_BADFID;
5865
5866         if (!Printer->document_started) {
5867                 return WERR_SPL_NO_STARTDOC;
5868         }
5869
5870         errcode = print_job_delete(p->session_info,
5871                                    p->msg_ctx,
5872                                    snum,
5873                                    Printer->jobid);
5874
5875         return errcode;
5876 }
5877
5878 /********************************************************************
5879  * called by spoolss_api_setprinter
5880  * when updating a printer description
5881  ********************************************************************/
5882
5883 static WERROR update_printer_sec(struct policy_handle *handle,
5884                                  struct pipes_struct *p,
5885                                  struct sec_desc_buf *secdesc_ctr)
5886 {
5887         struct spoolss_security_descriptor *new_secdesc = NULL;
5888         struct spoolss_security_descriptor *old_secdesc = NULL;
5889         const char *printer;
5890         WERROR result;
5891         int snum;
5892
5893         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5894
5895         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5896                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5897                          OUR_HANDLE(handle)));
5898
5899                 result = WERR_BADFID;
5900                 goto done;
5901         }
5902
5903         if (secdesc_ctr == NULL) {
5904                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5905                 result = WERR_INVALID_PARAM;
5906                 goto done;
5907         }
5908         printer = lp_const_servicename(snum);
5909
5910         /* Check the user has permissions to change the security
5911            descriptor.  By experimentation with two NT machines, the user
5912            requires Full Access to the printer to change security
5913            information. */
5914
5915         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5916                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5917                 result = WERR_ACCESS_DENIED;
5918                 goto done;
5919         }
5920
5921         /* NT seems to like setting the security descriptor even though
5922            nothing may have actually changed. */
5923         result = winreg_get_printer_secdesc(p->mem_ctx,
5924                                             get_session_info_system(),
5925                                             p->msg_ctx,
5926                                             printer,
5927                                             &old_secdesc);
5928         if (!W_ERROR_IS_OK(result)) {
5929                 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc() failed\n"));
5930                 result = WERR_BADFID;
5931                 goto done;
5932         }
5933
5934         if (DEBUGLEVEL >= 10) {
5935                 struct security_acl *the_acl;
5936                 int i;
5937
5938                 the_acl = old_secdesc->dacl;
5939                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5940                            printer, the_acl->num_aces));
5941
5942                 for (i = 0; i < the_acl->num_aces; i++) {
5943                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5944                                            &the_acl->aces[i].trustee),
5945                                   the_acl->aces[i].access_mask));
5946                 }
5947
5948                 the_acl = secdesc_ctr->sd->dacl;
5949
5950                 if (the_acl) {
5951                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5952                                    printer, the_acl->num_aces));
5953
5954                         for (i = 0; i < the_acl->num_aces; i++) {
5955                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5956                                                    &the_acl->aces[i].trustee),
5957                                            the_acl->aces[i].access_mask));
5958                         }
5959                 } else {
5960                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5961                 }
5962         }
5963
5964         new_secdesc = sec_desc_merge(p->mem_ctx, secdesc_ctr->sd, old_secdesc);
5965         if (new_secdesc == NULL) {
5966                 result = WERR_NOMEM;
5967                 goto done;
5968         }
5969
5970         if (security_descriptor_equal(new_secdesc, old_secdesc)) {
5971                 result = WERR_OK;
5972                 goto done;
5973         }
5974
5975         result = winreg_set_printer_secdesc(p->mem_ctx,
5976                                             get_session_info_system(),
5977                                             p->msg_ctx,
5978                                             printer,
5979                                             new_secdesc);
5980
5981  done:
5982         return result;
5983 }
5984
5985 /********************************************************************
5986  Canonicalize printer info from a client
5987  ********************************************************************/
5988
5989 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
5990                              struct spoolss_SetPrinterInfo2 *info2,
5991                              int snum)
5992 {
5993         fstring printername;
5994         const char *p;
5995
5996         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5997                 "portname=%s drivername=%s comment=%s location=%s\n",
5998                 info2->servername, info2->printername, info2->sharename,
5999                 info2->portname, info2->drivername, info2->comment,
6000                 info2->location));
6001
6002         /* we force some elements to "correct" values */
6003         info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
6004         if (info2->servername == NULL) {
6005                 return false;
6006         }
6007         info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6008         if (info2->sharename == NULL) {
6009                 return false;
6010         }
6011
6012         /* check to see if we allow printername != sharename */
6013         if (lp_force_printername(snum)) {
6014                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6015                                         global_myname(), info2->sharename);
6016         } else {
6017                 /* make sure printername is in \\server\printername format */
6018                 fstrcpy(printername, info2->printername);
6019                 p = printername;
6020                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6021                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6022                                 p++;
6023                 }
6024
6025                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6026                                         global_myname(), p);
6027         }
6028         if (info2->printername == NULL) {
6029                 return false;
6030         }
6031
6032         info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6033         info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6034
6035         return true;
6036 }
6037
6038 /****************************************************************************
6039 ****************************************************************************/
6040
6041 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6042 {
6043         char *cmd = lp_addport_cmd();
6044         char *command = NULL;
6045         int ret;
6046         bool is_print_op = false;
6047
6048         if ( !*cmd ) {
6049                 return WERR_ACCESS_DENIED;
6050         }
6051
6052         command = talloc_asprintf(ctx,
6053                         "%s \"%s\" \"%s\"", cmd, portname, uri );
6054         if (!command) {
6055                 return WERR_NOMEM;
6056         }
6057
6058         if ( token )
6059                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6060
6061         DEBUG(10,("Running [%s]\n", command));
6062
6063         /********* BEGIN SePrintOperatorPrivilege **********/
6064
6065         if ( is_print_op )
6066                 become_root();
6067
6068         ret = smbrun(command, NULL);
6069
6070         if ( is_print_op )
6071                 unbecome_root();
6072
6073         /********* END SePrintOperatorPrivilege **********/
6074
6075         DEBUGADD(10,("returned [%d]\n", ret));
6076
6077         TALLOC_FREE(command);
6078
6079         if ( ret != 0 ) {
6080                 return WERR_ACCESS_DENIED;
6081         }
6082
6083         return WERR_OK;
6084 }
6085
6086 /****************************************************************************
6087 ****************************************************************************/
6088
6089 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6090                              struct spoolss_SetPrinterInfo2 *info2,
6091                              const char *remote_machine,
6092                              struct messaging_context *msg_ctx)
6093 {
6094         char *cmd = lp_addprinter_cmd();
6095         char **qlines;
6096         char *command = NULL;
6097         int numlines;
6098         int ret;
6099         int fd;
6100         bool is_print_op = false;
6101
6102         if (!remote_machine) {
6103                 return false;
6104         }
6105
6106         command = talloc_asprintf(ctx,
6107                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6108                         cmd, info2->printername, info2->sharename,
6109                         info2->portname, info2->drivername,
6110                         info2->location, info2->comment, remote_machine);
6111         if (!command) {
6112                 return false;
6113         }
6114
6115         if ( token )
6116                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6117
6118         DEBUG(10,("Running [%s]\n", command));
6119
6120         /********* BEGIN SePrintOperatorPrivilege **********/
6121
6122         if ( is_print_op )
6123                 become_root();
6124
6125         if ( (ret = smbrun(command, &fd)) == 0 ) {
6126                 /* Tell everyone we updated smb.conf. */
6127                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6128         }
6129
6130         if ( is_print_op )
6131                 unbecome_root();
6132
6133         /********* END SePrintOperatorPrivilege **********/
6134
6135         DEBUGADD(10,("returned [%d]\n", ret));
6136
6137         TALLOC_FREE(command);
6138
6139         if ( ret != 0 ) {
6140                 if (fd != -1)
6141                         close(fd);
6142                 return false;
6143         }
6144
6145         /* reload our services immediately */
6146         become_root();
6147         reload_services(msg_ctx, -1, false);
6148         unbecome_root();
6149
6150         numlines = 0;
6151         /* Get lines and convert them back to dos-codepage */
6152         qlines = fd_lines_load(fd, &numlines, 0, NULL);
6153         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6154         close(fd);
6155
6156         /* Set the portname to what the script says the portname should be. */
6157         /* but don't require anything to be return from the script exit a good error code */
6158
6159         if (numlines) {
6160                 /* Set the portname to what the script says the portname should be. */
6161                 info2->portname = talloc_strdup(ctx, qlines[0]);
6162                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6163         }
6164
6165         TALLOC_FREE(qlines);
6166         return true;
6167 }
6168
6169 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6170                                const struct auth_serversupplied_info *session_info,
6171                                struct messaging_context *msg_ctx,
6172                                int snum,
6173                                struct spoolss_SetPrinterInfo2 *printer,
6174                                struct spoolss_PrinterInfo2 *old_printer)
6175 {
6176         bool force_update = (old_printer == NULL);
6177         const char *dnsdomname;
6178         const char *longname;
6179         const char *uncname;
6180         const char *spooling;
6181         DATA_BLOB buffer;
6182         WERROR result = WERR_OK;
6183
6184         if (force_update || !strequal(printer->drivername, old_printer->drivername)) {
6185                 push_reg_sz(mem_ctx, &buffer, printer->drivername);
6186                 winreg_set_printer_dataex(mem_ctx,
6187                                           session_info,
6188                                           msg_ctx,
6189                                           printer->sharename,
6190                                           SPOOL_DSSPOOLER_KEY,
6191                                           SPOOL_REG_DRIVERNAME,
6192                                           REG_SZ,
6193                                           buffer.data,
6194                                           buffer.length);
6195
6196                 if (!force_update) {
6197                         DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6198                                 printer->drivername));
6199
6200                         notify_printer_driver(server_event_context(), msg_ctx,
6201                                               snum, printer->drivername ?
6202                                               printer->drivername : "");
6203                 }
6204         }
6205
6206         if (force_update || !strequal(printer->comment, old_printer->comment)) {
6207                 push_reg_sz(mem_ctx, &buffer, printer->comment);
6208                 winreg_set_printer_dataex(mem_ctx,
6209                                           session_info,
6210                                           msg_ctx,
6211                                           printer->sharename,
6212                                           SPOOL_DSSPOOLER_KEY,
6213                                           SPOOL_REG_DESCRIPTION,
6214                                           REG_SZ,
6215                                           buffer.data,
6216                                           buffer.length);
6217
6218                 if (!force_update) {
6219                         notify_printer_comment(server_event_context(), msg_ctx,
6220                                                snum, printer->comment ?
6221                                                printer->comment : "");
6222                 }
6223         }
6224
6225         if (force_update || !strequal(printer->sharename, old_printer->sharename)) {
6226                 push_reg_sz(mem_ctx, &buffer, printer->sharename);
6227                 winreg_set_printer_dataex(mem_ctx,
6228                                           session_info,
6229                                           msg_ctx,
6230                                           printer->sharename,
6231                                           SPOOL_DSSPOOLER_KEY,
6232                                           SPOOL_REG_PRINTSHARENAME,
6233                                           REG_SZ,
6234                                           buffer.data,
6235                                           buffer.length);
6236
6237                 if (!force_update) {
6238                         notify_printer_sharename(server_event_context(),
6239                                                  msg_ctx,
6240                                                  snum, printer->sharename ?
6241                                                  printer->sharename : "");
6242                 }
6243         }
6244
6245         if (force_update || !strequal(printer->printername, old_printer->printername)) {
6246                 const char *p;
6247
6248                 p = strrchr(printer->printername, '\\' );
6249                 if (p != NULL) {
6250                         p++;
6251                 } else {
6252                         p = printer->printername;
6253                 }
6254
6255                 push_reg_sz(mem_ctx, &buffer, p);
6256                 winreg_set_printer_dataex(mem_ctx,
6257                                           session_info,
6258                                           msg_ctx,
6259                                           printer->sharename,
6260                                           SPOOL_DSSPOOLER_KEY,
6261                                           SPOOL_REG_PRINTERNAME,
6262                                           REG_SZ,
6263                                           buffer.data,
6264                                           buffer.length);
6265
6266                 if (!force_update) {
6267                         notify_printer_printername(server_event_context(),
6268                                                    msg_ctx, snum, p ? p : "");
6269                 }
6270         }
6271
6272         if (force_update || !strequal(printer->portname, old_printer->portname)) {
6273                 push_reg_sz(mem_ctx, &buffer, printer->portname);
6274                 winreg_set_printer_dataex(mem_ctx,
6275                                           session_info,
6276                                           msg_ctx,
6277                                           printer->sharename,
6278                                           SPOOL_DSSPOOLER_KEY,
6279                                           SPOOL_REG_PORTNAME,
6280                                           REG_SZ,
6281                                           buffer.data,
6282                                           buffer.length);
6283
6284                 if (!force_update) {
6285                         notify_printer_port(server_event_context(),
6286                                             msg_ctx, snum, printer->portname ?
6287                                             printer->portname : "");
6288                 }
6289         }
6290
6291         if (force_update || !strequal(printer->location, old_printer->location)) {
6292                 push_reg_sz(mem_ctx, &buffer, printer->location);
6293                 winreg_set_printer_dataex(mem_ctx,
6294                                           session_info,
6295                                           msg_ctx,
6296                                           printer->sharename,
6297                                           SPOOL_DSSPOOLER_KEY,
6298                                           SPOOL_REG_LOCATION,
6299                                           REG_SZ,
6300                                           buffer.data,
6301                                           buffer.length);
6302
6303                 if (!force_update) {
6304                         notify_printer_location(server_event_context(),
6305                                                 msg_ctx, snum,
6306                                                 printer->location ?
6307                                                 printer->location : "");
6308                 }
6309         }
6310
6311         if (force_update || !strequal(printer->sepfile, old_printer->sepfile)) {
6312                 push_reg_sz(mem_ctx, &buffer, printer->sepfile);
6313                 winreg_set_printer_dataex(mem_ctx,
6314                                           session_info,
6315                                           msg_ctx,
6316                                           printer->sharename,
6317                                           SPOOL_DSSPOOLER_KEY,
6318                                           SPOOL_REG_PRINTSEPARATORFILE,
6319                                           REG_SZ,
6320                                           buffer.data,
6321                                           buffer.length);
6322
6323                 if (!force_update) {
6324                         notify_printer_sepfile(server_event_context(),
6325                                                msg_ctx, snum,
6326                                                printer->sepfile ?
6327                                                printer->sepfile : "");
6328                 }
6329         }
6330
6331         if (force_update || printer->starttime != old_printer->starttime) {
6332                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6333                 SIVAL(buffer.data, 0, printer->starttime);
6334                 winreg_set_printer_dataex(mem_ctx,
6335                                           session_info,
6336                                           msg_ctx,
6337                                           printer->sharename,
6338                                           SPOOL_DSSPOOLER_KEY,
6339                                           SPOOL_REG_PRINTSTARTTIME,
6340                                           REG_DWORD,
6341                                           buffer.data,
6342                                           buffer.length);
6343         }
6344
6345         if (force_update || printer->untiltime != old_printer->untiltime) {
6346                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6347                 SIVAL(buffer.data, 0, printer->untiltime);
6348                 winreg_set_printer_dataex(mem_ctx,
6349                                           session_info,
6350                                           msg_ctx,
6351                                           printer->sharename,
6352                                           SPOOL_DSSPOOLER_KEY,
6353                                           SPOOL_REG_PRINTENDTIME,
6354                                           REG_DWORD,
6355                                           buffer.data,
6356                                           buffer.length);
6357         }
6358
6359         if (force_update || printer->priority != old_printer->priority) {
6360                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6361                 SIVAL(buffer.data, 0, printer->priority);
6362                 winreg_set_printer_dataex(mem_ctx,
6363                                           session_info,
6364                                           msg_ctx,
6365                                           printer->sharename,
6366                                           SPOOL_DSSPOOLER_KEY,
6367                                           SPOOL_REG_PRIORITY,
6368                                           REG_DWORD,
6369                                           buffer.data,
6370                                           buffer.length);
6371         }
6372
6373         if (force_update || printer->attributes != old_printer->attributes) {
6374                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6375                 SIVAL(buffer.data, 0, (printer->attributes &
6376                                        PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6377                 winreg_set_printer_dataex(mem_ctx,
6378                                           session_info,
6379                                           msg_ctx,
6380                                           printer->sharename,
6381                                           SPOOL_DSSPOOLER_KEY,
6382                                           SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6383                                           REG_DWORD,
6384                                           buffer.data,
6385                                           buffer.length);
6386
6387                 switch (printer->attributes & 0x3) {
6388                         case 0:
6389                                 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6390                                 break;
6391                         case 1:
6392                                 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6393                                 break;
6394                         case 2:
6395                                 spooling = SPOOL_REGVAL_PRINTDIRECT;
6396                                 break;
6397                         default:
6398                                 spooling = "unknown";
6399                 }
6400                 push_reg_sz(mem_ctx, &buffer, spooling);
6401                 winreg_set_printer_dataex(mem_ctx,
6402                                           session_info,
6403                                           msg_ctx,
6404                                           printer->sharename,
6405                                           SPOOL_DSSPOOLER_KEY,
6406                                           SPOOL_REG_PRINTSPOOLING,
6407                                           REG_SZ,
6408                                           buffer.data,
6409                                           buffer.length);
6410         }
6411
6412         push_reg_sz(mem_ctx, &buffer, global_myname());
6413         winreg_set_printer_dataex(mem_ctx,
6414                                   session_info,
6415                                   msg_ctx,
6416                                   printer->sharename,
6417                                   SPOOL_DSSPOOLER_KEY,
6418                                   SPOOL_REG_SHORTSERVERNAME,
6419                                   REG_SZ,
6420                                   buffer.data,
6421                                   buffer.length);
6422
6423         dnsdomname = get_mydnsfullname();
6424         if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6425                 longname = talloc_strdup(mem_ctx, dnsdomname);
6426         } else {
6427                 longname = talloc_strdup(mem_ctx, global_myname());
6428         }
6429         if (longname == NULL) {
6430                 result = WERR_NOMEM;
6431                 goto done;
6432         }
6433
6434         push_reg_sz(mem_ctx, &buffer, longname);
6435         winreg_set_printer_dataex(mem_ctx,
6436                                   session_info,
6437                                   msg_ctx,
6438                                   printer->sharename,
6439                                   SPOOL_DSSPOOLER_KEY,
6440                                   SPOOL_REG_SERVERNAME,
6441                                   REG_SZ,
6442                                   buffer.data,
6443                                   buffer.length);
6444
6445         uncname = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6446                                   global_myname(), printer->sharename);
6447         push_reg_sz(mem_ctx, &buffer, uncname);
6448         winreg_set_printer_dataex(mem_ctx,
6449                                   session_info,
6450                                   msg_ctx,
6451                                   printer->sharename,
6452                                   SPOOL_DSSPOOLER_KEY,
6453                                   SPOOL_REG_UNCNAME,
6454                                   REG_SZ,
6455                                   buffer.data,
6456                                   buffer.length);
6457
6458 done:
6459         return result;
6460 }
6461
6462 /********************************************************************
6463  * Called by spoolss_api_setprinter
6464  * when updating a printer description.
6465  ********************************************************************/
6466
6467 static WERROR update_printer(struct pipes_struct *p,
6468                              struct policy_handle *handle,
6469                              struct spoolss_SetPrinterInfoCtr *info_ctr,
6470                              struct spoolss_DeviceMode *devmode)
6471 {
6472         uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6473         struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6474         struct spoolss_PrinterInfo2 *old_printer;
6475         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6476         int snum;
6477         WERROR result = WERR_OK;
6478         TALLOC_CTX *tmp_ctx;
6479
6480         DEBUG(8,("update_printer\n"));
6481
6482         tmp_ctx = talloc_new(p->mem_ctx);
6483         if (tmp_ctx == NULL) {
6484                 return WERR_NOMEM;
6485         }
6486
6487         if (!Printer) {
6488                 result = WERR_BADFID;
6489                 goto done;
6490         }
6491
6492         if (!get_printer_snum(p, handle, &snum, NULL)) {
6493                 result = WERR_BADFID;
6494                 goto done;
6495         }
6496
6497         result = winreg_get_printer(tmp_ctx,
6498                                     get_session_info_system(),
6499                                     p->msg_ctx,
6500                                     lp_const_servicename(snum),
6501                                     &old_printer);
6502         if (!W_ERROR_IS_OK(result)) {
6503                 result = WERR_BADFID;
6504                 goto done;
6505         }
6506
6507         /* Do sanity check on the requested changes for Samba */
6508         if (!check_printer_ok(tmp_ctx, printer, snum)) {
6509                 result = WERR_INVALID_PARAM;
6510                 goto done;
6511         }
6512
6513         /* FIXME!!! If the driver has changed we really should verify that
6514            it is installed before doing much else   --jerry */
6515
6516         /* Check calling user has permission to update printer description */
6517         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6518                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6519                 result = WERR_ACCESS_DENIED;
6520                 goto done;
6521         }
6522
6523         /* Call addprinter hook */
6524         /* Check changes to see if this is really needed */
6525
6526         if (*lp_addprinter_cmd() &&
6527                         (!strequal(printer->drivername, old_printer->drivername) ||
6528                          !strequal(printer->comment, old_printer->comment) ||
6529                          !strequal(printer->portname, old_printer->portname) ||
6530                          !strequal(printer->location, old_printer->location)) )
6531         {
6532                 /* add_printer_hook() will call reload_services() */
6533                 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6534                                       printer, p->client_id->addr,
6535                                       p->msg_ctx)) {
6536                         result = WERR_ACCESS_DENIED;
6537                         goto done;
6538                 }
6539         }
6540
6541         update_dsspooler(tmp_ctx,
6542                          get_session_info_system(),
6543                          p->msg_ctx,
6544                          snum,
6545                          printer,
6546                          old_printer);
6547
6548         printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6549
6550         if (devmode == NULL) {
6551                 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6552         }
6553         result = winreg_update_printer(tmp_ctx,
6554                                        get_session_info_system(),
6555                                        p->msg_ctx,
6556                                        printer->sharename,
6557                                        printer_mask,
6558                                        printer,
6559                                        devmode,
6560                                        NULL);
6561
6562 done:
6563         talloc_free(tmp_ctx);
6564
6565         return result;
6566 }
6567
6568 /****************************************************************************
6569 ****************************************************************************/
6570 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6571                                            struct policy_handle *handle,
6572                                            struct spoolss_SetPrinterInfo7 *info7)
6573 {
6574 #ifdef HAVE_ADS
6575         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6576         WERROR result;
6577         int snum;
6578         struct printer_handle *Printer;
6579
6580         if ( lp_security() != SEC_ADS ) {
6581                 return WERR_UNKNOWN_LEVEL;
6582         }
6583
6584         Printer = find_printer_index_by_hnd(p, handle);
6585
6586         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6587
6588         if (!Printer)
6589                 return WERR_BADFID;
6590
6591         if (!get_printer_snum(p, handle, &snum, NULL))
6592                 return WERR_BADFID;
6593
6594         result = winreg_get_printer(p->mem_ctx,
6595                                     get_session_info_system(),
6596                                     p->msg_ctx,
6597                                     lp_servicename(snum),
6598                                     &pinfo2);
6599         if (!W_ERROR_IS_OK(result)) {
6600                 return WERR_BADFID;
6601         }
6602
6603         nt_printer_publish(pinfo2,
6604                            get_session_info_system(),
6605                            p->msg_ctx,
6606                            pinfo2,
6607                            info7->action);
6608
6609         TALLOC_FREE(pinfo2);
6610         return WERR_OK;
6611 #else
6612         return WERR_UNKNOWN_LEVEL;
6613 #endif
6614 }
6615
6616 /********************************************************************
6617  ********************************************************************/
6618
6619 static WERROR update_printer_devmode(struct pipes_struct *p,
6620                                      struct policy_handle *handle,
6621                                      struct spoolss_DeviceMode *devmode)
6622 {
6623         int snum;
6624         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6625         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6626
6627         DEBUG(8,("update_printer_devmode\n"));
6628
6629         if (!Printer) {
6630                 return WERR_BADFID;
6631         }
6632
6633         if (!get_printer_snum(p, handle, &snum, NULL)) {
6634                 return WERR_BADFID;
6635         }
6636
6637         /* Check calling user has permission to update printer description */
6638         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6639                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6640                 return WERR_ACCESS_DENIED;
6641         }
6642
6643         return winreg_update_printer(p->mem_ctx,
6644                                      get_session_info_system(),
6645                                      p->msg_ctx,
6646                                      lp_const_servicename(snum),
6647                                      info2_mask,
6648                                      NULL,
6649                                      devmode,
6650                                      NULL);
6651 }
6652
6653
6654 /****************************************************************
6655  _spoolss_SetPrinter
6656 ****************************************************************/
6657
6658 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6659                            struct spoolss_SetPrinter *r)
6660 {
6661         WERROR result;
6662
6663         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6664
6665         if (!Printer) {
6666                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6667                         OUR_HANDLE(r->in.handle)));
6668                 return WERR_BADFID;
6669         }
6670
6671         /* check the level */
6672         switch (r->in.info_ctr->level) {
6673                 case 0:
6674                         return control_printer(r->in.handle, r->in.command, p);
6675                 case 2:
6676                         result = update_printer(p, r->in.handle,
6677                                                 r->in.info_ctr,
6678                                                 r->in.devmode_ctr->devmode);
6679                         if (!W_ERROR_IS_OK(result))
6680                                 return result;
6681                         if (r->in.secdesc_ctr->sd)
6682                                 result = update_printer_sec(r->in.handle, p,
6683                                                             r->in.secdesc_ctr);
6684                         return result;
6685                 case 3:
6686                         return update_printer_sec(r->in.handle, p,
6687                                                   r->in.secdesc_ctr);
6688                 case 7:
6689                         return publish_or_unpublish_printer(p, r->in.handle,
6690                                                             r->in.info_ctr->info.info7);
6691                 case 8:
6692                         return update_printer_devmode(p, r->in.handle,
6693                                                       r->in.devmode_ctr->devmode);
6694                 default:
6695                         return WERR_UNKNOWN_LEVEL;
6696         }
6697 }
6698
6699 /****************************************************************
6700  _spoolss_FindClosePrinterNotify
6701 ****************************************************************/
6702
6703 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
6704                                        struct spoolss_FindClosePrinterNotify *r)
6705 {
6706         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6707
6708         if (!Printer) {
6709                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6710                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6711                 return WERR_BADFID;
6712         }
6713
6714         if (Printer->notify.cli_chan != NULL &&
6715             Printer->notify.cli_chan->active_connections > 0) {
6716                 int snum = -1;
6717
6718                 if (Printer->printer_type == SPLHND_PRINTER) {
6719                         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6720                                 return WERR_BADFID;
6721                         }
6722                 }
6723
6724                 srv_spoolss_replycloseprinter(snum, Printer);
6725         }
6726
6727         Printer->notify.flags=0;
6728         Printer->notify.options=0;
6729         Printer->notify.localmachine[0]='\0';
6730         Printer->notify.printerlocal=0;
6731         TALLOC_FREE(Printer->notify.option);
6732
6733         return WERR_OK;
6734 }
6735
6736 /****************************************************************
6737  _spoolss_AddJob
6738 ****************************************************************/
6739
6740 WERROR _spoolss_AddJob(struct pipes_struct *p,
6741                        struct spoolss_AddJob *r)
6742 {
6743         if (!r->in.buffer && (r->in.offered != 0)) {
6744                 return WERR_INVALID_PARAM;
6745         }
6746
6747         /* this is what a NT server returns for AddJob. AddJob must fail on
6748          * non-local printers */
6749
6750         if (r->in.level != 1) {
6751                 return WERR_UNKNOWN_LEVEL;
6752         }
6753
6754         return WERR_INVALID_PARAM;
6755 }
6756
6757 /****************************************************************************
6758 fill_job_info1
6759 ****************************************************************************/
6760
6761 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6762                              struct spoolss_JobInfo1 *r,
6763                              const print_queue_struct *queue,
6764                              int position, int snum,
6765                              struct spoolss_PrinterInfo2 *pinfo2)
6766 {
6767         struct tm *t;
6768
6769         t = gmtime(&queue->time);
6770
6771         r->job_id               = queue->job;
6772
6773         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6774         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6775         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
6776         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6777         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6778         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6779         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6780         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6781         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6782         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6783         r->text_status          = talloc_strdup(mem_ctx, "");
6784         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6785
6786         r->status               = nt_printj_status(queue->status);
6787         r->priority             = queue->priority;
6788         r->position             = position;
6789         r->total_pages          = queue->page_count;
6790         r->pages_printed        = 0; /* ??? */
6791
6792         init_systemtime(&r->submitted, t);
6793
6794         return WERR_OK;
6795 }
6796
6797 /****************************************************************************
6798 fill_job_info2
6799 ****************************************************************************/
6800
6801 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6802                              struct spoolss_JobInfo2 *r,
6803                              const print_queue_struct *queue,
6804                              int position, int snum,
6805                              struct spoolss_PrinterInfo2 *pinfo2,
6806                              struct spoolss_DeviceMode *devmode)
6807 {
6808         struct tm *t;
6809
6810         t = gmtime(&queue->time);
6811
6812         r->job_id               = queue->job;
6813
6814         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6815         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6816         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
6817         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6818         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6819         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6820         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6821         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6822         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
6823         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6824         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6825         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6826         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
6827         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6828         r->parameters           = talloc_strdup(mem_ctx, "");
6829         W_ERROR_HAVE_NO_MEMORY(r->parameters);
6830         r->driver_name          = talloc_strdup(mem_ctx, pinfo2->drivername);
6831         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6832
6833         r->devmode              = devmode;
6834
6835         r->text_status          = talloc_strdup(mem_ctx, "");
6836         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6837
6838         r->secdesc              = NULL;
6839
6840         r->status               = nt_printj_status(queue->status);
6841         r->priority             = queue->priority;
6842         r->position             = position;
6843         r->start_time           = 0;
6844         r->until_time           = 0;
6845         r->total_pages          = queue->page_count;
6846         r->size                 = queue->size;
6847         init_systemtime(&r->submitted, t);
6848         r->time                 = 0;
6849         r->pages_printed        = 0; /* ??? */
6850
6851         return WERR_OK;
6852 }
6853
6854 /****************************************************************************
6855 fill_job_info3
6856 ****************************************************************************/
6857
6858 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6859                              struct spoolss_JobInfo3 *r,
6860                              const print_queue_struct *queue,
6861                              const print_queue_struct *next_queue,
6862                              int position, int snum,
6863                              struct spoolss_PrinterInfo2 *pinfo2)
6864 {
6865         r->job_id               = queue->job;
6866         r->next_job_id          = 0;
6867         if (next_queue) {
6868                 r->next_job_id  = next_queue->job;
6869         }
6870         r->reserved             = 0;
6871
6872         return WERR_OK;
6873 }
6874
6875 /****************************************************************************
6876  Enumjobs at level 1.
6877 ****************************************************************************/
6878
6879 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6880                               const print_queue_struct *queue,
6881                               uint32_t num_queues, int snum,
6882                               struct spoolss_PrinterInfo2 *pinfo2,
6883                               union spoolss_JobInfo **info_p,
6884                               uint32_t *count)
6885 {
6886         union spoolss_JobInfo *info;
6887         int i;
6888         WERROR result = WERR_OK;
6889
6890         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6891         W_ERROR_HAVE_NO_MEMORY(info);
6892
6893         *count = num_queues;
6894
6895         for (i=0; i<*count; i++) {
6896                 result = fill_job_info1(info,
6897                                         &info[i].info1,
6898                                         &queue[i],
6899                                         i,
6900                                         snum,
6901                                         pinfo2);
6902                 if (!W_ERROR_IS_OK(result)) {
6903                         goto out;
6904                 }
6905         }
6906
6907  out:
6908         if (!W_ERROR_IS_OK(result)) {
6909                 TALLOC_FREE(info);
6910                 *count = 0;
6911                 return result;
6912         }
6913
6914         *info_p = info;
6915
6916         return WERR_OK;
6917 }
6918
6919 /****************************************************************************
6920  Enumjobs at level 2.
6921 ****************************************************************************/
6922
6923 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6924                               const print_queue_struct *queue,
6925                               uint32_t num_queues, int snum,
6926                               struct spoolss_PrinterInfo2 *pinfo2,
6927                               union spoolss_JobInfo **info_p,
6928                               uint32_t *count)
6929 {
6930         union spoolss_JobInfo *info;
6931         int i;
6932         WERROR result = WERR_OK;
6933
6934         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6935         W_ERROR_HAVE_NO_MEMORY(info);
6936
6937         *count = num_queues;
6938
6939         for (i=0; i<*count; i++) {
6940                 struct spoolss_DeviceMode *devmode;
6941
6942                 result = spoolss_create_default_devmode(info,
6943                                                         pinfo2->printername,
6944                                                         &devmode);
6945                 if (!W_ERROR_IS_OK(result)) {
6946                         DEBUG(3, ("Can't proceed w/o a devmode!"));
6947                         goto out;
6948                 }
6949
6950                 result = fill_job_info2(info,
6951                                         &info[i].info2,
6952                                         &queue[i],
6953                                         i,
6954                                         snum,
6955                                         pinfo2,
6956                                         devmode);
6957                 if (!W_ERROR_IS_OK(result)) {
6958                         goto out;
6959                 }
6960         }
6961
6962  out:
6963         if (!W_ERROR_IS_OK(result)) {
6964                 TALLOC_FREE(info);
6965                 *count = 0;
6966                 return result;
6967         }
6968
6969         *info_p = info;
6970
6971         return WERR_OK;
6972 }
6973
6974 /****************************************************************************
6975  Enumjobs at level 3.
6976 ****************************************************************************/
6977
6978 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
6979                               const print_queue_struct *queue,
6980                               uint32_t num_queues, int snum,
6981                               struct spoolss_PrinterInfo2 *pinfo2,
6982                               union spoolss_JobInfo **info_p,
6983                               uint32_t *count)
6984 {
6985         union spoolss_JobInfo *info;
6986         int i;
6987         WERROR result = WERR_OK;
6988
6989         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6990         W_ERROR_HAVE_NO_MEMORY(info);
6991
6992         *count = num_queues;
6993
6994         for (i=0; i<*count; i++) {
6995                 const print_queue_struct *next_queue = NULL;
6996
6997                 if (i+1 < *count) {
6998                         next_queue = &queue[i+1];
6999                 }
7000
7001                 result = fill_job_info3(info,
7002                                         &info[i].info3,
7003                                         &queue[i],
7004                                         next_queue,
7005                                         i,
7006                                         snum,
7007                                         pinfo2);
7008                 if (!W_ERROR_IS_OK(result)) {
7009                         goto out;
7010                 }
7011         }
7012
7013  out:
7014         if (!W_ERROR_IS_OK(result)) {
7015                 TALLOC_FREE(info);
7016                 *count = 0;
7017                 return result;
7018         }
7019
7020         *info_p = info;
7021
7022         return WERR_OK;
7023 }
7024
7025 /****************************************************************
7026  _spoolss_EnumJobs
7027 ****************************************************************/
7028
7029 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7030                          struct spoolss_EnumJobs *r)
7031 {
7032         WERROR result;
7033         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7034         int snum;
7035         print_status_struct prt_status;
7036         print_queue_struct *queue = NULL;
7037         uint32_t count;
7038
7039         /* that's an [in out] buffer */
7040
7041         if (!r->in.buffer && (r->in.offered != 0)) {
7042                 return WERR_INVALID_PARAM;
7043         }
7044
7045         DEBUG(4,("_spoolss_EnumJobs\n"));
7046
7047         *r->out.needed = 0;
7048         *r->out.count = 0;
7049         *r->out.info = NULL;
7050
7051         /* lookup the printer snum and tdb entry */
7052
7053         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7054                 return WERR_BADFID;
7055         }
7056
7057         result = winreg_get_printer(p->mem_ctx,
7058                                     get_session_info_system(),
7059                                     p->msg_ctx,
7060                                     lp_const_servicename(snum),
7061                                     &pinfo2);
7062         if (!W_ERROR_IS_OK(result)) {
7063                 return result;
7064         }
7065
7066         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7067         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7068                 count, prt_status.status, prt_status.message));
7069
7070         if (count == 0) {
7071                 SAFE_FREE(queue);
7072                 TALLOC_FREE(pinfo2);
7073                 return WERR_OK;
7074         }
7075
7076         switch (r->in.level) {
7077         case 1:
7078                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7079                                          pinfo2, r->out.info, r->out.count);
7080                 break;
7081         case 2:
7082                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7083                                          pinfo2, r->out.info, r->out.count);
7084                 break;
7085         case 3:
7086                 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7087                                          pinfo2, r->out.info, r->out.count);
7088                 break;
7089         default:
7090                 result = WERR_UNKNOWN_LEVEL;
7091                 break;
7092         }
7093
7094         SAFE_FREE(queue);
7095         TALLOC_FREE(pinfo2);
7096
7097         if (!W_ERROR_IS_OK(result)) {
7098                 return result;
7099         }
7100
7101         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7102                                                      spoolss_EnumJobs,
7103                                                      *r->out.info, r->in.level,
7104                                                      *r->out.count);
7105         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7106         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7107
7108         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7109 }
7110
7111 /****************************************************************
7112  _spoolss_ScheduleJob
7113 ****************************************************************/
7114
7115 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7116                             struct spoolss_ScheduleJob *r)
7117 {
7118         return WERR_OK;
7119 }
7120
7121 /****************************************************************
7122 ****************************************************************/
7123
7124 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7125                                struct messaging_context *msg_ctx,
7126                                const char *printer_name,
7127                                uint32_t job_id,
7128                                struct spoolss_SetJobInfo1 *r)
7129 {
7130         char *old_doc_name;
7131
7132         if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7133                 return WERR_BADFID;
7134         }
7135
7136         if (strequal(old_doc_name, r->document_name)) {
7137                 return WERR_OK;
7138         }
7139
7140         if (!print_job_set_name(server_event_context(), msg_ctx,
7141                                 printer_name, job_id, r->document_name)) {
7142                 return WERR_BADFID;
7143         }
7144
7145         return WERR_OK;
7146 }
7147
7148 /****************************************************************
7149  _spoolss_SetJob
7150 ****************************************************************/
7151
7152 WERROR _spoolss_SetJob(struct pipes_struct *p,
7153                        struct spoolss_SetJob *r)
7154 {
7155         const struct auth_serversupplied_info *session_info = p->session_info;
7156         int snum;
7157         WERROR errcode = WERR_BADFUNC;
7158
7159         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7160                 return WERR_BADFID;
7161         }
7162
7163         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7164                 return WERR_INVALID_PRINTER_NAME;
7165         }
7166
7167         switch (r->in.command) {
7168         case SPOOLSS_JOB_CONTROL_CANCEL:
7169         case SPOOLSS_JOB_CONTROL_DELETE:
7170                 errcode = print_job_delete(session_info, p->msg_ctx,
7171                                            snum, r->in.job_id);
7172                 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7173                         errcode = WERR_OK;
7174                 }
7175                 break;
7176         case SPOOLSS_JOB_CONTROL_PAUSE:
7177                 if (print_job_pause(session_info, p->msg_ctx,
7178                                     snum, r->in.job_id, &errcode)) {
7179                         errcode = WERR_OK;
7180                 }
7181                 break;
7182         case SPOOLSS_JOB_CONTROL_RESTART:
7183         case SPOOLSS_JOB_CONTROL_RESUME:
7184                 if (print_job_resume(session_info, p->msg_ctx,
7185                                      snum, r->in.job_id, &errcode)) {
7186                         errcode = WERR_OK;
7187                 }
7188                 break;
7189         case 0:
7190                 errcode = WERR_OK;
7191                 break;
7192         default:
7193                 return WERR_UNKNOWN_LEVEL;
7194         }
7195
7196         if (!W_ERROR_IS_OK(errcode)) {
7197                 return errcode;
7198         }
7199
7200         if (r->in.ctr == NULL) {
7201                 return errcode;
7202         }
7203
7204         switch (r->in.ctr->level) {
7205         case 1:
7206                 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7207                                            lp_const_servicename(snum),
7208                                            r->in.job_id,
7209                                            r->in.ctr->info.info1);
7210                 break;
7211         case 2:
7212         case 3:
7213         case 4:
7214         default:
7215                 return WERR_UNKNOWN_LEVEL;
7216         }
7217
7218         return errcode;
7219 }
7220
7221 /****************************************************************************
7222  Enumerates all printer drivers by level and architecture.
7223 ****************************************************************************/
7224
7225 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7226                                                        const struct auth_serversupplied_info *session_info,
7227                                                        struct messaging_context *msg_ctx,
7228                                                        const char *servername,
7229                                                        const char *architecture,
7230                                                        uint32_t level,
7231                                                        union spoolss_DriverInfo **info_p,
7232                                                        uint32_t *count_p)
7233 {
7234         int i;
7235         uint32_t version;
7236         struct spoolss_DriverInfo8 *driver;
7237         union spoolss_DriverInfo *info = NULL;
7238         uint32_t count = 0;
7239         WERROR result = WERR_OK;
7240         uint32_t num_drivers;
7241         const char **drivers;
7242
7243         *count_p = 0;
7244         *info_p = NULL;
7245
7246         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7247                 result = winreg_get_driver_list(mem_ctx, session_info, msg_ctx,
7248                                                 architecture, version,
7249                                                 &num_drivers, &drivers);
7250                 if (!W_ERROR_IS_OK(result)) {
7251                         goto out;
7252                 }
7253                 DEBUG(4, ("we have:[%d] drivers in environment"
7254                           " [%s] and version [%d]\n",
7255                           num_drivers, architecture, version));
7256
7257                 if (num_drivers != 0) {
7258                         info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
7259                                                     union spoolss_DriverInfo,
7260                                                     count + num_drivers);
7261                         if (!info) {
7262                                 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7263                                         "failed to enlarge driver info buffer!\n"));
7264                                 result = WERR_NOMEM;
7265                                 goto out;
7266                         }
7267                 }
7268
7269                 for (i = 0; i < num_drivers; i++) {
7270                         DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7271
7272                         result = winreg_get_driver(mem_ctx, session_info,
7273                                                    msg_ctx,
7274                                                    architecture, drivers[i],
7275                                                    version, &driver);
7276                         if (!W_ERROR_IS_OK(result)) {
7277                                 goto out;
7278                         }
7279
7280                         switch (level) {
7281                         case 1:
7282                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
7283                                                                    driver, servername);
7284                                 break;
7285                         case 2:
7286                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
7287                                                                    driver, servername);
7288                                 break;
7289                         case 3:
7290                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
7291                                                                    driver, servername);
7292                                 break;
7293                         case 4:
7294                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
7295                                                                    driver, servername);
7296                                 break;
7297                         case 5:
7298                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
7299                                                                    driver, servername);
7300                                 break;
7301                         case 6:
7302                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
7303                                                                    driver, servername);
7304                                 break;
7305                         case 8:
7306                                 result = fill_printer_driver_info8(info, &info[count+i].info8,
7307                                                                    driver, servername);
7308                                 break;
7309                         default:
7310                                 result = WERR_UNKNOWN_LEVEL;
7311                                 break;
7312                         }
7313
7314                         TALLOC_FREE(driver);
7315
7316                         if (!W_ERROR_IS_OK(result)) {
7317                                 goto out;
7318                         }
7319                 }
7320
7321                 count += num_drivers;
7322                 TALLOC_FREE(drivers);
7323         }
7324
7325  out:
7326         TALLOC_FREE(drivers);
7327
7328         if (!W_ERROR_IS_OK(result)) {
7329                 TALLOC_FREE(info);
7330                 return result;
7331         }
7332
7333         *info_p = info;
7334         *count_p = count;
7335
7336         return WERR_OK;
7337 }
7338
7339 /****************************************************************************
7340  Enumerates all printer drivers by level.
7341 ****************************************************************************/
7342
7343 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7344                                        const struct auth_serversupplied_info *session_info,
7345                                        struct messaging_context *msg_ctx,
7346                                        const char *servername,
7347                                        const char *architecture,
7348                                        uint32_t level,
7349                                        union spoolss_DriverInfo **info_p,
7350                                        uint32_t *count_p)
7351 {
7352         uint32_t a,i;
7353         WERROR result = WERR_OK;
7354
7355         if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7356
7357                 for (a=0; archi_table[a].long_archi != NULL; a++) {
7358
7359                         union spoolss_DriverInfo *info = NULL;
7360                         uint32_t count = 0;
7361
7362                         result = enumprinterdrivers_level_by_architecture(mem_ctx,
7363                                                                           session_info,
7364                                                                           msg_ctx,
7365                                                                           servername,
7366                                                                           archi_table[a].long_archi,
7367                                                                           level,
7368                                                                           &info,
7369                                                                           &count);
7370                         if (!W_ERROR_IS_OK(result)) {
7371                                 continue;
7372                         }
7373
7374                         for (i=0; i < count; i++) {
7375                                 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7376                                              info[i], info_p, count_p);
7377                         }
7378                 }
7379
7380                 return result;
7381         }
7382
7383         return enumprinterdrivers_level_by_architecture(mem_ctx,
7384                                                         session_info,
7385                                                         msg_ctx,
7386                                                         servername,
7387                                                         architecture,
7388                                                         level,
7389                                                         info_p,
7390                                                         count_p);
7391 }
7392
7393 /****************************************************************
7394  _spoolss_EnumPrinterDrivers
7395 ****************************************************************/
7396
7397 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7398                                    struct spoolss_EnumPrinterDrivers *r)
7399 {
7400         const char *cservername;
7401         WERROR result;
7402
7403         /* that's an [in out] buffer */
7404
7405         if (!r->in.buffer && (r->in.offered != 0)) {
7406                 return WERR_INVALID_PARAM;
7407         }
7408
7409         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7410
7411         *r->out.needed = 0;
7412         *r->out.count = 0;
7413         *r->out.info = NULL;
7414
7415         cservername = canon_servername(r->in.server);
7416
7417         if (!is_myname_or_ipaddr(cservername)) {
7418                 return WERR_UNKNOWN_PRINTER_DRIVER;
7419         }
7420
7421         result = enumprinterdrivers_level(p->mem_ctx,
7422                                           get_session_info_system(),
7423                                           p->msg_ctx,
7424                                           cservername,
7425                                           r->in.environment,
7426                                           r->in.level,
7427                                           r->out.info,
7428                                           r->out.count);
7429         if (!W_ERROR_IS_OK(result)) {
7430                 return result;
7431         }
7432
7433         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7434                                                      spoolss_EnumPrinterDrivers,
7435                                                      *r->out.info, r->in.level,
7436                                                      *r->out.count);
7437         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7438         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7439
7440         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7441 }
7442
7443 /****************************************************************
7444  _spoolss_EnumForms
7445 ****************************************************************/
7446
7447 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7448                           struct spoolss_EnumForms *r)
7449 {
7450         WERROR result;
7451
7452         *r->out.count = 0;
7453         *r->out.needed = 0;
7454         *r->out.info = NULL;
7455
7456         /* that's an [in out] buffer */
7457
7458         if (!r->in.buffer && (r->in.offered != 0) ) {
7459                 return WERR_INVALID_PARAM;
7460         }
7461
7462         DEBUG(4,("_spoolss_EnumForms\n"));
7463         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7464         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7465
7466         switch (r->in.level) {
7467         case 1:
7468                 result = winreg_printer_enumforms1(p->mem_ctx,
7469                                                    get_session_info_system(),
7470                                                    p->msg_ctx,
7471                                                    r->out.count,
7472                                                    r->out.info);
7473                 break;
7474         default:
7475                 result = WERR_UNKNOWN_LEVEL;
7476                 break;
7477         }
7478
7479         if (!W_ERROR_IS_OK(result)) {
7480                 return result;
7481         }
7482
7483         if (*r->out.count == 0) {
7484                 return WERR_NO_MORE_ITEMS;
7485         }
7486
7487         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7488                                                      spoolss_EnumForms,
7489                                                      *r->out.info, r->in.level,
7490                                                      *r->out.count);
7491         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7492         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7493
7494         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7495 }
7496
7497 /****************************************************************
7498  _spoolss_GetForm
7499 ****************************************************************/
7500
7501 WERROR _spoolss_GetForm(struct pipes_struct *p,
7502                         struct spoolss_GetForm *r)
7503 {
7504         WERROR result;
7505
7506         /* that's an [in out] buffer */
7507
7508         if (!r->in.buffer && (r->in.offered != 0)) {
7509                 return WERR_INVALID_PARAM;
7510         }
7511
7512         DEBUG(4,("_spoolss_GetForm\n"));
7513         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7514         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7515
7516         switch (r->in.level) {
7517         case 1:
7518                 result = winreg_printer_getform1(p->mem_ctx,
7519                                                  get_session_info_system(),
7520                                                  p->msg_ctx,
7521                                                  r->in.form_name,
7522                                                  &r->out.info->info1);
7523                 break;
7524         default:
7525                 result = WERR_UNKNOWN_LEVEL;
7526                 break;
7527         }
7528
7529         if (!W_ERROR_IS_OK(result)) {
7530                 TALLOC_FREE(r->out.info);
7531                 return result;
7532         }
7533
7534         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
7535                                                r->out.info, r->in.level);
7536         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7537
7538         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7539 }
7540
7541 /****************************************************************************
7542 ****************************************************************************/
7543
7544 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7545                           struct spoolss_PortInfo1 *r,
7546                           const char *name)
7547 {
7548         r->port_name = talloc_strdup(mem_ctx, name);
7549         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7550
7551         return WERR_OK;
7552 }
7553
7554 /****************************************************************************
7555  TODO: This probably needs distinguish between TCP/IP and Local ports
7556  somehow.
7557 ****************************************************************************/
7558
7559 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7560                           struct spoolss_PortInfo2 *r,
7561                           const char *name)
7562 {
7563         r->port_name = talloc_strdup(mem_ctx, name);
7564         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7565
7566         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7567         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7568
7569         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7570         W_ERROR_HAVE_NO_MEMORY(r->description);
7571
7572         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7573         r->reserved = 0;
7574
7575         return WERR_OK;
7576 }
7577
7578
7579 /****************************************************************************
7580  wrapper around the enumer ports command
7581 ****************************************************************************/
7582
7583 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7584 {
7585         char *cmd = lp_enumports_cmd();
7586         char **qlines = NULL;
7587         char *command = NULL;
7588         int numlines;
7589         int ret;
7590         int fd;
7591
7592         *count = 0;
7593         *lines = NULL;
7594
7595         /* if no hook then just fill in the default port */
7596
7597         if ( !*cmd ) {
7598                 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7599                         return WERR_NOMEM;
7600                 }
7601                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7602                         TALLOC_FREE(qlines);
7603                         return WERR_NOMEM;
7604                 }
7605                 qlines[1] = NULL;
7606                 numlines = 1;
7607         }
7608         else {
7609                 /* we have a valid enumport command */
7610
7611                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7612                 if (!command) {
7613                         return WERR_NOMEM;
7614                 }
7615
7616                 DEBUG(10,("Running [%s]\n", command));
7617                 ret = smbrun(command, &fd);
7618                 DEBUG(10,("Returned [%d]\n", ret));
7619                 TALLOC_FREE(command);
7620                 if (ret != 0) {
7621                         if (fd != -1) {
7622                                 close(fd);
7623                         }
7624                         return WERR_ACCESS_DENIED;
7625                 }
7626
7627                 numlines = 0;
7628                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7629                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7630                 close(fd);
7631         }
7632
7633         *count = numlines;
7634         *lines = qlines;
7635
7636         return WERR_OK;
7637 }
7638
7639 /****************************************************************************
7640  enumports level 1.
7641 ****************************************************************************/
7642
7643 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7644                                 union spoolss_PortInfo **info_p,
7645                                 uint32_t *count)
7646 {
7647         union spoolss_PortInfo *info = NULL;
7648         int i=0;
7649         WERROR result = WERR_OK;
7650         char **qlines = NULL;
7651         int numlines = 0;
7652
7653         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7654         if (!W_ERROR_IS_OK(result)) {
7655                 goto out;
7656         }
7657
7658         if (numlines) {
7659                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7660                 if (!info) {
7661                         DEBUG(10,("Returning WERR_NOMEM\n"));
7662                         result = WERR_NOMEM;
7663                         goto out;
7664                 }
7665
7666                 for (i=0; i<numlines; i++) {
7667                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7668                         result = fill_port_1(info, &info[i].info1, qlines[i]);
7669                         if (!W_ERROR_IS_OK(result)) {
7670                                 goto out;
7671                         }
7672                 }
7673         }
7674         TALLOC_FREE(qlines);
7675
7676 out:
7677         if (!W_ERROR_IS_OK(result)) {
7678                 TALLOC_FREE(info);
7679                 TALLOC_FREE(qlines);
7680                 *count = 0;
7681                 *info_p = NULL;
7682                 return result;
7683         }
7684
7685         *info_p = info;
7686         *count = numlines;
7687
7688         return WERR_OK;
7689 }
7690
7691 /****************************************************************************
7692  enumports level 2.
7693 ****************************************************************************/
7694
7695 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7696                                 union spoolss_PortInfo **info_p,
7697                                 uint32_t *count)
7698 {
7699         union spoolss_PortInfo *info = NULL;
7700         int i=0;
7701         WERROR result = WERR_OK;
7702         char **qlines = NULL;
7703         int numlines = 0;
7704
7705         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7706         if (!W_ERROR_IS_OK(result)) {
7707                 goto out;
7708         }
7709
7710         if (numlines) {
7711                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7712                 if (!info) {
7713                         DEBUG(10,("Returning WERR_NOMEM\n"));
7714                         result = WERR_NOMEM;
7715                         goto out;
7716                 }
7717
7718                 for (i=0; i<numlines; i++) {
7719                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7720                         result = fill_port_2(info, &info[i].info2, qlines[i]);
7721                         if (!W_ERROR_IS_OK(result)) {
7722                                 goto out;
7723                         }
7724                 }
7725         }
7726         TALLOC_FREE(qlines);
7727
7728 out:
7729         if (!W_ERROR_IS_OK(result)) {
7730                 TALLOC_FREE(info);
7731                 TALLOC_FREE(qlines);
7732                 *count = 0;
7733                 *info_p = NULL;
7734                 return result;
7735         }
7736
7737         *info_p = info;
7738         *count = numlines;
7739
7740         return WERR_OK;
7741 }
7742
7743 /****************************************************************
7744  _spoolss_EnumPorts
7745 ****************************************************************/
7746
7747 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
7748                           struct spoolss_EnumPorts *r)
7749 {
7750         WERROR result;
7751
7752         /* that's an [in out] buffer */
7753
7754         if (!r->in.buffer && (r->in.offered != 0)) {
7755                 return WERR_INVALID_PARAM;
7756         }
7757
7758         DEBUG(4,("_spoolss_EnumPorts\n"));
7759
7760         *r->out.count = 0;
7761         *r->out.needed = 0;
7762         *r->out.info = NULL;
7763
7764         switch (r->in.level) {
7765         case 1:
7766                 result = enumports_level_1(p->mem_ctx, r->out.info,
7767                                            r->out.count);
7768                 break;
7769         case 2:
7770                 result = enumports_level_2(p->mem_ctx, r->out.info,
7771                                            r->out.count);
7772                 break;
7773         default:
7774                 return WERR_UNKNOWN_LEVEL;
7775         }
7776
7777         if (!W_ERROR_IS_OK(result)) {
7778                 return result;
7779         }
7780
7781         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7782                                                      spoolss_EnumPorts,
7783                                                      *r->out.info, r->in.level,
7784                                                      *r->out.count);
7785         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7786         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7787
7788         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7789 }
7790
7791 /****************************************************************************
7792 ****************************************************************************/
7793
7794 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
7795                                            const char *server,
7796                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
7797                                            struct spoolss_DeviceMode *devmode,
7798                                            struct security_descriptor *secdesc,
7799                                            struct spoolss_UserLevelCtr *user_ctr,
7800                                            struct policy_handle *handle)
7801 {
7802         struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
7803         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
7804         int     snum;
7805         WERROR err = WERR_OK;
7806
7807         /* samba does not have a concept of local, non-shared printers yet, so
7808          * make sure we always setup sharename - gd */
7809         if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
7810             (info2->printername != NULL && info2->printername[0] != '\0')) {
7811                 DEBUG(5, ("spoolss_addprinterex_level_2: "
7812                         "no sharename has been set, setting printername %s as sharename\n",
7813                         info2->printername));
7814                 info2->sharename = info2->printername;
7815         }
7816
7817         /* check to see if the printer already exists */
7818         if ((snum = print_queue_snum(info2->sharename)) != -1) {
7819                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7820                         info2->sharename));
7821                 return WERR_PRINTER_ALREADY_EXISTS;
7822         }
7823
7824         if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7825                 if ((snum = print_queue_snum(info2->printername)) != -1) {
7826                         DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7827                                 info2->printername));
7828                         return WERR_PRINTER_ALREADY_EXISTS;
7829                 }
7830         }
7831
7832         /* validate printer info struct */
7833         if (!info2->printername || strlen(info2->printername) == 0) {
7834                 return WERR_INVALID_PRINTER_NAME;
7835         }
7836         if (!info2->portname || strlen(info2->portname) == 0) {
7837                 return WERR_UNKNOWN_PORT;
7838         }
7839         if (!info2->drivername || strlen(info2->drivername) == 0) {
7840                 return WERR_UNKNOWN_PRINTER_DRIVER;
7841         }
7842         if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
7843                 return WERR_UNKNOWN_PRINTPROCESSOR;
7844         }
7845
7846         /* FIXME!!!  smbd should check to see if the driver is installed before
7847            trying to add a printer like this  --jerry */
7848
7849         if (*lp_addprinter_cmd() ) {
7850                 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
7851                                        info2, p->client_id->addr,
7852                                        p->msg_ctx) ) {
7853                         return WERR_ACCESS_DENIED;
7854                 }
7855         } else {
7856                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7857                         "smb.conf parameter \"addprinter command\" is defined. This"
7858                         "parameter must exist for this call to succeed\n",
7859                         info2->sharename ));
7860         }
7861
7862         if ((snum = print_queue_snum(info2->sharename)) == -1) {
7863                 return WERR_ACCESS_DENIED;
7864         }
7865
7866         /* you must be a printer admin to add a new printer */
7867         if (!print_access_check(p->session_info,
7868                                 p->msg_ctx,
7869                                 snum,
7870                                 PRINTER_ACCESS_ADMINISTER)) {
7871                 return WERR_ACCESS_DENIED;
7872         }
7873
7874         /*
7875          * Do sanity check on the requested changes for Samba.
7876          */
7877
7878         if (!check_printer_ok(p->mem_ctx, info2, snum)) {
7879                 return WERR_INVALID_PARAM;
7880         }
7881
7882         if (devmode == NULL) {
7883                 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
7884         }
7885
7886         update_dsspooler(p->mem_ctx,
7887                          get_session_info_system(),
7888                          p->msg_ctx,
7889                          0,
7890                          info2,
7891                          NULL);
7892
7893         err = winreg_update_printer(p->mem_ctx,
7894                                     get_session_info_system(),
7895                                     p->msg_ctx,
7896                                     info2->sharename,
7897                                     info2_mask,
7898                                     info2,
7899                                     devmode,
7900                                     secdesc);
7901         if (!W_ERROR_IS_OK(err)) {
7902                 return err;
7903         }
7904
7905         err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
7906         if (!W_ERROR_IS_OK(err)) {
7907                 /* Handle open failed - remove addition. */
7908                 ZERO_STRUCTP(handle);
7909                 return err;
7910         }
7911
7912         return WERR_OK;
7913 }
7914
7915 /****************************************************************
7916  _spoolss_AddPrinterEx
7917 ****************************************************************/
7918
7919 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
7920                              struct spoolss_AddPrinterEx *r)
7921 {
7922         switch (r->in.info_ctr->level) {
7923         case 1:
7924                 /* we don't handle yet */
7925                 /* but I know what to do ... */
7926                 return WERR_UNKNOWN_LEVEL;
7927         case 2:
7928                 return spoolss_addprinterex_level_2(p, r->in.server,
7929                                                     r->in.info_ctr,
7930                                                     r->in.devmode_ctr->devmode,
7931                                                     r->in.secdesc_ctr->sd,
7932                                                     r->in.userlevel_ctr,
7933                                                     r->out.handle);
7934         default:
7935                 return WERR_UNKNOWN_LEVEL;
7936         }
7937 }
7938
7939 /****************************************************************
7940  _spoolss_AddPrinter
7941 ****************************************************************/
7942
7943 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
7944                            struct spoolss_AddPrinter *r)
7945 {
7946         struct spoolss_AddPrinterEx a;
7947         struct spoolss_UserLevelCtr userlevel_ctr;
7948
7949         ZERO_STRUCT(userlevel_ctr);
7950
7951         userlevel_ctr.level = 1;
7952
7953         a.in.server             = r->in.server;
7954         a.in.info_ctr           = r->in.info_ctr;
7955         a.in.devmode_ctr        = r->in.devmode_ctr;
7956         a.in.secdesc_ctr        = r->in.secdesc_ctr;
7957         a.in.userlevel_ctr      = &userlevel_ctr;
7958         a.out.handle            = r->out.handle;
7959
7960         return _spoolss_AddPrinterEx(p, &a);
7961 }
7962
7963 /****************************************************************
7964  _spoolss_AddPrinterDriverEx
7965 ****************************************************************/
7966
7967 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
7968                                    struct spoolss_AddPrinterDriverEx *r)
7969 {
7970         WERROR err = WERR_OK;
7971         const char *driver_name = NULL;
7972         uint32_t version;
7973         const char *fn;
7974
7975         switch (p->opnum) {
7976                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7977                         fn = "_spoolss_AddPrinterDriver";
7978                         break;
7979                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7980                         fn = "_spoolss_AddPrinterDriverEx";
7981                         break;
7982                 default:
7983                         return WERR_INVALID_PARAM;
7984         }
7985
7986         /*
7987          * we only support the semantics of AddPrinterDriver()
7988          * i.e. only copy files that are newer than existing ones
7989          */
7990
7991         if (r->in.flags == 0) {
7992                 return WERR_INVALID_PARAM;
7993         }
7994
7995         if (r->in.flags != APD_COPY_NEW_FILES) {
7996                 return WERR_ACCESS_DENIED;
7997         }
7998
7999         /* FIXME */
8000         if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
8001                 /* Clever hack from Martin Zielinski <mz@seh.de>
8002                  * to allow downgrade from level 8 (Vista).
8003                  */
8004                 DEBUG(0,("%s: level %d not yet implemented\n", fn,
8005                         r->in.info_ctr->level));
8006                 return WERR_UNKNOWN_LEVEL;
8007         }
8008
8009         DEBUG(5,("Cleaning driver's information\n"));
8010         err = clean_up_driver_struct(p->mem_ctx, p, r->in.info_ctr);
8011         if (!W_ERROR_IS_OK(err))
8012                 goto done;
8013
8014         DEBUG(5,("Moving driver to final destination\n"));
8015         err = move_driver_to_download_area(p, r->in.info_ctr);
8016         if (!W_ERROR_IS_OK(err)) {
8017                 goto done;
8018         }
8019
8020         err = winreg_add_driver(p->mem_ctx,
8021                                 get_session_info_system(),
8022                                 p->msg_ctx,
8023                                 r->in.info_ctr,
8024                                 &driver_name,
8025                                 &version);
8026         if (!W_ERROR_IS_OK(err)) {
8027                 goto done;
8028         }
8029
8030         /*
8031          * I think this is where he DrvUpgradePrinter() hook would be
8032          * be called in a driver's interface DLL on a Windows NT 4.0/2k
8033          * server.  Right now, we just need to send ourselves a message
8034          * to update each printer bound to this driver.   --jerry
8035          */
8036
8037         if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8038                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8039                         fn, driver_name));
8040         }
8041
8042 done:
8043         return err;
8044 }
8045
8046 /****************************************************************
8047  _spoolss_AddPrinterDriver
8048 ****************************************************************/
8049
8050 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8051                                  struct spoolss_AddPrinterDriver *r)
8052 {
8053         struct spoolss_AddPrinterDriverEx a;
8054
8055         switch (r->in.info_ctr->level) {
8056         case 2:
8057         case 3:
8058         case 4:
8059         case 5:
8060                 break;
8061         default:
8062                 return WERR_UNKNOWN_LEVEL;
8063         }
8064
8065         a.in.servername         = r->in.servername;
8066         a.in.info_ctr           = r->in.info_ctr;
8067         a.in.flags              = APD_COPY_NEW_FILES;
8068
8069         return _spoolss_AddPrinterDriverEx(p, &a);
8070 }
8071
8072 /****************************************************************************
8073 ****************************************************************************/
8074
8075 struct _spoolss_paths {
8076         int type;
8077         const char *share;
8078         const char *dir;
8079 };
8080
8081 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8082
8083 static const struct _spoolss_paths spoolss_paths[]= {
8084         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
8085         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
8086 };
8087
8088 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8089                                           const char *servername,
8090                                           const char *environment,
8091                                           int component,
8092                                           char **path)
8093 {
8094         const char *pservername = NULL;
8095         const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
8096         const char *short_archi;
8097
8098         *path = NULL;
8099
8100         /* environment may be empty */
8101         if (environment && strlen(environment)) {
8102                 long_archi = environment;
8103         }
8104
8105         /* servername may be empty */
8106         if (servername && strlen(servername)) {
8107                 pservername = canon_servername(servername);
8108
8109                 if (!is_myname_or_ipaddr(pservername)) {
8110                         return WERR_INVALID_PARAM;
8111                 }
8112         }
8113
8114         if (!(short_archi = get_short_archi(long_archi))) {
8115                 return WERR_INVALID_ENVIRONMENT;
8116         }
8117
8118         switch (component) {
8119         case SPOOLSS_PRTPROCS_PATH:
8120         case SPOOLSS_DRIVER_PATH:
8121                 if (pservername) {
8122                         *path = talloc_asprintf(mem_ctx,
8123                                         "\\\\%s\\%s\\%s",
8124                                         pservername,
8125                                         spoolss_paths[component].share,
8126                                         short_archi);
8127                 } else {
8128                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8129                                         SPOOLSS_DEFAULT_SERVER_PATH,
8130                                         spoolss_paths[component].dir,
8131                                         short_archi);
8132                 }
8133                 break;
8134         default:
8135                 return WERR_INVALID_PARAM;
8136         }
8137
8138         if (!*path) {
8139                 return WERR_NOMEM;
8140         }
8141
8142         return WERR_OK;
8143 }
8144
8145 /****************************************************************************
8146 ****************************************************************************/
8147
8148 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8149                                           const char *servername,
8150                                           const char *environment,
8151                                           struct spoolss_DriverDirectoryInfo1 *r)
8152 {
8153         WERROR werr;
8154         char *path = NULL;
8155
8156         werr = compose_spoolss_server_path(mem_ctx,
8157                                            servername,
8158                                            environment,
8159                                            SPOOLSS_DRIVER_PATH,
8160                                            &path);
8161         if (!W_ERROR_IS_OK(werr)) {
8162                 return werr;
8163         }
8164
8165         DEBUG(4,("printer driver directory: [%s]\n", path));
8166
8167         r->directory_name = path;
8168
8169         return WERR_OK;
8170 }
8171
8172 /****************************************************************
8173  _spoolss_GetPrinterDriverDirectory
8174 ****************************************************************/
8175
8176 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8177                                           struct spoolss_GetPrinterDriverDirectory *r)
8178 {
8179         WERROR werror;
8180
8181         /* that's an [in out] buffer */
8182
8183         if (!r->in.buffer && (r->in.offered != 0)) {
8184                 return WERR_INVALID_PARAM;
8185         }
8186
8187         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8188                 r->in.level));
8189
8190         *r->out.needed = 0;
8191
8192         /* r->in.level is ignored */
8193
8194         werror = getprinterdriverdir_level_1(p->mem_ctx,
8195                                              r->in.server,
8196                                              r->in.environment,
8197                                              &r->out.info->info1);
8198         if (!W_ERROR_IS_OK(werror)) {
8199                 TALLOC_FREE(r->out.info);
8200                 return werror;
8201         }
8202
8203         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8204                                                r->out.info, r->in.level);
8205         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8206
8207         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8208 }
8209
8210 /****************************************************************
8211  _spoolss_EnumPrinterData
8212 ****************************************************************/
8213
8214 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8215                                 struct spoolss_EnumPrinterData *r)
8216 {
8217         WERROR result;
8218         struct spoolss_EnumPrinterDataEx r2;
8219         uint32_t count;
8220         struct spoolss_PrinterEnumValues *info, *val = NULL;
8221         uint32_t needed;
8222
8223         r2.in.handle    = r->in.handle;
8224         r2.in.key_name  = "PrinterDriverData";
8225         r2.in.offered   = 0;
8226         r2.out.count    = &count;
8227         r2.out.info     = &info;
8228         r2.out.needed   = &needed;
8229
8230         result = _spoolss_EnumPrinterDataEx(p, &r2);
8231         if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8232                 r2.in.offered = needed;
8233                 result = _spoolss_EnumPrinterDataEx(p, &r2);
8234         }
8235         if (!W_ERROR_IS_OK(result)) {
8236                 return result;
8237         }
8238
8239         /*
8240          * The NT machine wants to know the biggest size of value and data
8241          *
8242          * cf: MSDN EnumPrinterData remark section
8243          */
8244
8245         if (!r->in.value_offered && !r->in.data_offered) {
8246                 uint32_t biggest_valuesize = 0;
8247                 uint32_t biggest_datasize = 0;
8248                 int i, name_length;
8249
8250                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8251
8252                 for (i=0; i<count; i++) {
8253
8254                         name_length = strlen(info[i].value_name);
8255                         if (strlen(info[i].value_name) > biggest_valuesize) {
8256                                 biggest_valuesize = name_length;
8257                         }
8258
8259                         if (info[i].data_length > biggest_datasize) {
8260                                 biggest_datasize = info[i].data_length;
8261                         }
8262
8263                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8264                                 biggest_datasize));
8265                 }
8266
8267                 /* the value is an UNICODE string but real_value_size is the length
8268                    in bytes including the trailing 0 */
8269
8270                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8271                 *r->out.data_needed  = biggest_datasize;
8272
8273                 DEBUG(6,("final values: [%d], [%d]\n",
8274                         *r->out.value_needed, *r->out.data_needed));
8275
8276                 return WERR_OK;
8277         }
8278
8279         if (r->in.enum_index < count) {
8280                 val = &info[r->in.enum_index];
8281         }
8282
8283         if (val == NULL) {
8284                 /* out_value should default to "" or else NT4 has
8285                    problems unmarshalling the response */
8286
8287                 if (r->in.value_offered) {
8288                         *r->out.value_needed = 1;
8289                         r->out.value_name = talloc_strdup(r, "");
8290                         if (!r->out.value_name) {
8291                                 return WERR_NOMEM;
8292                         }
8293                 } else {
8294                         r->out.value_name = NULL;
8295                         *r->out.value_needed = 0;
8296                 }
8297
8298                 /* the data is counted in bytes */
8299
8300                 *r->out.data_needed = r->in.data_offered;
8301
8302                 result = WERR_NO_MORE_ITEMS;
8303         } else {
8304                 /*
8305                  * the value is:
8306                  * - counted in bytes in the request
8307                  * - counted in UNICODE chars in the max reply
8308                  * - counted in bytes in the real size
8309                  *
8310                  * take a pause *before* coding not *during* coding
8311                  */
8312
8313                 /* name */
8314                 if (r->in.value_offered) {
8315                         r->out.value_name = talloc_strdup(r, val->value_name);
8316                         if (!r->out.value_name) {
8317                                 return WERR_NOMEM;
8318                         }
8319                         *r->out.value_needed = val->value_name_len;
8320                 } else {
8321                         r->out.value_name = NULL;
8322                         *r->out.value_needed = 0;
8323                 }
8324
8325                 /* type */
8326
8327                 *r->out.type = val->type;
8328
8329                 /* data - counted in bytes */
8330
8331                 /*
8332                  * See the section "Dynamically Typed Query Parameters"
8333                  * in MS-RPRN.
8334                  */
8335
8336                 if (r->out.data && val->data && val->data->data &&
8337                                 val->data_length && r->in.data_offered) {
8338                         memcpy(r->out.data, val->data->data,
8339                                 MIN(val->data_length,r->in.data_offered));
8340                 }
8341
8342                 *r->out.data_needed = val->data_length;
8343
8344                 result = WERR_OK;
8345         }
8346
8347         return result;
8348 }
8349
8350 /****************************************************************
8351  _spoolss_SetPrinterData
8352 ****************************************************************/
8353
8354 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8355                                struct spoolss_SetPrinterData *r)
8356 {
8357         struct spoolss_SetPrinterDataEx r2;
8358
8359         r2.in.handle            = r->in.handle;
8360         r2.in.key_name          = "PrinterDriverData";
8361         r2.in.value_name        = r->in.value_name;
8362         r2.in.type              = r->in.type;
8363         r2.in.data              = r->in.data;
8364         r2.in.offered           = r->in.offered;
8365
8366         return _spoolss_SetPrinterDataEx(p, &r2);
8367 }
8368
8369 /****************************************************************
8370  _spoolss_ResetPrinter
8371 ****************************************************************/
8372
8373 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8374                              struct spoolss_ResetPrinter *r)
8375 {
8376         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8377         int             snum;
8378
8379         DEBUG(5,("_spoolss_ResetPrinter\n"));
8380
8381         /*
8382          * All we do is to check to see if the handle and queue is valid.
8383          * This call really doesn't mean anything to us because we only
8384          * support RAW printing.   --jerry
8385          */
8386
8387         if (!Printer) {
8388                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8389                         OUR_HANDLE(r->in.handle)));
8390                 return WERR_BADFID;
8391         }
8392
8393         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8394                 return WERR_BADFID;
8395
8396
8397         /* blindly return success */
8398         return WERR_OK;
8399 }
8400
8401 /****************************************************************
8402  _spoolss_DeletePrinterData
8403 ****************************************************************/
8404
8405 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8406                                   struct spoolss_DeletePrinterData *r)
8407 {
8408         struct spoolss_DeletePrinterDataEx r2;
8409
8410         r2.in.handle            = r->in.handle;
8411         r2.in.key_name          = "PrinterDriverData";
8412         r2.in.value_name        = r->in.value_name;
8413
8414         return _spoolss_DeletePrinterDataEx(p, &r2);
8415 }
8416
8417 /****************************************************************
8418  _spoolss_AddForm
8419 ****************************************************************/
8420
8421 WERROR _spoolss_AddForm(struct pipes_struct *p,
8422                         struct spoolss_AddForm *r)
8423 {
8424         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8425         int snum = -1;
8426         WERROR status = WERR_OK;
8427
8428         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8429
8430         DEBUG(5,("_spoolss_AddForm\n"));
8431
8432         if (!Printer) {
8433                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8434                         OUR_HANDLE(r->in.handle)));
8435                 return WERR_BADFID;
8436         }
8437
8438         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8439            and not a printer admin, then fail */
8440
8441         if ((p->session_info->utok.uid != sec_initial_uid()) &&
8442             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8443             !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8444                                           p->session_info->info3->base.domain.string,
8445                                           NULL,
8446                                           p->session_info->security_token,
8447                                           lp_printer_admin(snum))) {
8448                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8449                 return WERR_ACCESS_DENIED;
8450         }
8451
8452         switch (form->flags) {
8453         case SPOOLSS_FORM_USER:
8454         case SPOOLSS_FORM_BUILTIN:
8455         case SPOOLSS_FORM_PRINTER:
8456                 break;
8457         default:
8458                 return WERR_INVALID_PARAM;
8459         }
8460
8461         status = winreg_printer_addform1(p->mem_ctx,
8462                                          get_session_info_system(),
8463                                          p->msg_ctx,
8464                                          form);
8465         if (!W_ERROR_IS_OK(status)) {
8466                 return status;
8467         }
8468
8469         /*
8470          * ChangeID must always be set if this is a printer
8471          */
8472         if (Printer->printer_type == SPLHND_PRINTER) {
8473                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8474                         return WERR_BADFID;
8475                 }
8476
8477                 status = winreg_printer_update_changeid(p->mem_ctx,
8478                                                         get_session_info_system(),
8479                                                         p->msg_ctx,
8480                                                         lp_const_servicename(snum));
8481                 if (!W_ERROR_IS_OK(status)) {
8482                         return status;
8483                 }
8484         }
8485
8486         return status;
8487 }
8488
8489 /****************************************************************
8490  _spoolss_DeleteForm
8491 ****************************************************************/
8492
8493 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8494                            struct spoolss_DeleteForm *r)
8495 {
8496         const char *form_name = r->in.form_name;
8497         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8498         int snum = -1;
8499         WERROR status = WERR_OK;
8500
8501         DEBUG(5,("_spoolss_DeleteForm\n"));
8502
8503         if (!Printer) {
8504                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8505                         OUR_HANDLE(r->in.handle)));
8506                 return WERR_BADFID;
8507         }
8508
8509         if ((p->session_info->utok.uid != sec_initial_uid()) &&
8510             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8511             !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8512                                           p->session_info->info3->base.domain.string,
8513                                           NULL,
8514                                           p->session_info->security_token,
8515                                           lp_printer_admin(snum))) {
8516                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8517                 return WERR_ACCESS_DENIED;
8518         }
8519
8520         status = winreg_printer_deleteform1(p->mem_ctx,
8521                                             get_session_info_system(),
8522                                             p->msg_ctx,
8523                                             form_name);
8524         if (!W_ERROR_IS_OK(status)) {
8525                 return status;
8526         }
8527
8528         /*
8529          * ChangeID must always be set if this is a printer
8530          */
8531         if (Printer->printer_type == SPLHND_PRINTER) {
8532                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8533                         return WERR_BADFID;
8534                 }
8535
8536                 status = winreg_printer_update_changeid(p->mem_ctx,
8537                                                         get_session_info_system(),
8538                                                         p->msg_ctx,
8539                                                         lp_const_servicename(snum));
8540                 if (!W_ERROR_IS_OK(status)) {
8541                         return status;
8542                 }
8543         }
8544
8545         return status;
8546 }
8547
8548 /****************************************************************
8549  _spoolss_SetForm
8550 ****************************************************************/
8551
8552 WERROR _spoolss_SetForm(struct pipes_struct *p,
8553                         struct spoolss_SetForm *r)
8554 {
8555         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8556         const char *form_name = r->in.form_name;
8557         int snum = -1;
8558         WERROR status = WERR_OK;
8559
8560         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8561
8562         DEBUG(5,("_spoolss_SetForm\n"));
8563
8564         if (!Printer) {
8565                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8566                         OUR_HANDLE(r->in.handle)));
8567                 return WERR_BADFID;
8568         }
8569
8570         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8571            and not a printer admin, then fail */
8572
8573         if ((p->session_info->utok.uid != sec_initial_uid()) &&
8574              !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8575              !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8576                                           p->session_info->info3->base.domain.string,
8577                                           NULL,
8578                                           p->session_info->security_token,
8579                                           lp_printer_admin(snum))) {
8580                 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8581                 return WERR_ACCESS_DENIED;
8582         }
8583
8584         status = winreg_printer_setform1(p->mem_ctx,
8585                                          get_session_info_system(),
8586                                          p->msg_ctx,
8587                                          form_name,
8588                                          form);
8589         if (!W_ERROR_IS_OK(status)) {
8590                 return status;
8591         }
8592
8593         /*
8594          * ChangeID must always be set if this is a printer
8595          */
8596         if (Printer->printer_type == SPLHND_PRINTER) {
8597                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8598                         return WERR_BADFID;
8599                 }
8600
8601                 status = winreg_printer_update_changeid(p->mem_ctx,
8602                                                         get_session_info_system(),
8603                                                         p->msg_ctx,
8604                                                         lp_const_servicename(snum));
8605                 if (!W_ERROR_IS_OK(status)) {
8606                         return status;
8607                 }
8608         }
8609
8610         return status;
8611 }
8612
8613 /****************************************************************************
8614  fill_print_processor1
8615 ****************************************************************************/
8616
8617 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8618                                     struct spoolss_PrintProcessorInfo1 *r,
8619                                     const char *print_processor_name)
8620 {
8621         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8622         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8623
8624         return WERR_OK;
8625 }
8626
8627 /****************************************************************************
8628  enumprintprocessors level 1.
8629 ****************************************************************************/
8630
8631 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8632                                           union spoolss_PrintProcessorInfo **info_p,
8633                                           uint32_t *count)
8634 {
8635         union spoolss_PrintProcessorInfo *info;
8636         WERROR result;
8637
8638         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8639         W_ERROR_HAVE_NO_MEMORY(info);
8640
8641         *count = 1;
8642
8643         result = fill_print_processor1(info, &info[0].info1, "winprint");
8644         if (!W_ERROR_IS_OK(result)) {
8645                 goto out;
8646         }
8647
8648  out:
8649         if (!W_ERROR_IS_OK(result)) {
8650                 TALLOC_FREE(info);
8651                 *count = 0;
8652                 return result;
8653         }
8654
8655         *info_p = info;
8656
8657         return WERR_OK;
8658 }
8659
8660 /****************************************************************
8661  _spoolss_EnumPrintProcessors
8662 ****************************************************************/
8663
8664 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
8665                                     struct spoolss_EnumPrintProcessors *r)
8666 {
8667         WERROR result;
8668
8669         /* that's an [in out] buffer */
8670
8671         if (!r->in.buffer && (r->in.offered != 0)) {
8672                 return WERR_INVALID_PARAM;
8673         }
8674
8675         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8676
8677         /*
8678          * Enumerate the print processors ...
8679          *
8680          * Just reply with "winprint", to keep NT happy
8681          * and I can use my nice printer checker.
8682          */
8683
8684         *r->out.count = 0;
8685         *r->out.needed = 0;
8686         *r->out.info = NULL;
8687
8688         if (!get_short_archi(r->in.environment)) {
8689                 return WERR_INVALID_ENVIRONMENT;
8690         }
8691
8692         switch (r->in.level) {
8693         case 1:
8694                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8695                                                      r->out.count);
8696                 break;
8697         default:
8698                 return WERR_UNKNOWN_LEVEL;
8699         }
8700
8701         if (!W_ERROR_IS_OK(result)) {
8702                 return result;
8703         }
8704
8705         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8706                                                      spoolss_EnumPrintProcessors,
8707                                                      *r->out.info, r->in.level,
8708                                                      *r->out.count);
8709         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8710         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8711
8712         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8713 }
8714
8715 /****************************************************************************
8716  fill_printprocdatatype1
8717 ****************************************************************************/
8718
8719 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8720                                       struct spoolss_PrintProcDataTypesInfo1 *r,
8721                                       const char *name_array)
8722 {
8723         r->name_array = talloc_strdup(mem_ctx, name_array);
8724         W_ERROR_HAVE_NO_MEMORY(r->name_array);
8725
8726         return WERR_OK;
8727 }
8728
8729 /****************************************************************************
8730  enumprintprocdatatypes level 1.
8731 ****************************************************************************/
8732
8733 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8734                                              union spoolss_PrintProcDataTypesInfo **info_p,
8735                                              uint32_t *count)
8736 {
8737         WERROR result;
8738         union spoolss_PrintProcDataTypesInfo *info;
8739
8740         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8741         W_ERROR_HAVE_NO_MEMORY(info);
8742
8743         *count = 1;
8744
8745         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8746         if (!W_ERROR_IS_OK(result)) {
8747                 goto out;
8748         }
8749
8750  out:
8751         if (!W_ERROR_IS_OK(result)) {
8752                 TALLOC_FREE(info);
8753                 *count = 0;
8754                 return result;
8755         }
8756
8757         *info_p = info;
8758
8759         return WERR_OK;
8760 }
8761
8762 /****************************************************************
8763  _spoolss_EnumPrintProcDataTypes
8764 ****************************************************************/
8765
8766 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
8767                                        struct spoolss_EnumPrintProcDataTypes *r)
8768 {
8769         WERROR result;
8770
8771         /* that's an [in out] buffer */
8772
8773         if (!r->in.buffer && (r->in.offered != 0)) {
8774                 return WERR_INVALID_PARAM;
8775         }
8776
8777         DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8778
8779         *r->out.count = 0;
8780         *r->out.needed = 0;
8781         *r->out.info = NULL;
8782
8783         if (r->in.print_processor_name == NULL ||
8784             !strequal(r->in.print_processor_name, "winprint")) {
8785                 return WERR_UNKNOWN_PRINTPROCESSOR;
8786         }
8787
8788         switch (r->in.level) {
8789         case 1:
8790                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8791                                                         r->out.count);
8792                 break;
8793         default:
8794                 return WERR_UNKNOWN_LEVEL;
8795         }
8796
8797         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8798                                                      spoolss_EnumPrintProcDataTypes,
8799                                                      *r->out.info, r->in.level,
8800                                                      *r->out.count);
8801         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8802         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8803
8804         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8805 }
8806
8807 /****************************************************************************
8808  fill_monitor_1
8809 ****************************************************************************/
8810
8811 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8812                              struct spoolss_MonitorInfo1 *r,
8813                              const char *monitor_name)
8814 {
8815         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8816         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8817
8818         return WERR_OK;
8819 }
8820
8821 /****************************************************************************
8822  fill_monitor_2
8823 ****************************************************************************/
8824
8825 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8826                              struct spoolss_MonitorInfo2 *r,
8827                              const char *monitor_name,
8828                              const char *environment,
8829                              const char *dll_name)
8830 {
8831         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8832         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8833         r->environment                  = talloc_strdup(mem_ctx, environment);
8834         W_ERROR_HAVE_NO_MEMORY(r->environment);
8835         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
8836         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8837
8838         return WERR_OK;
8839 }
8840
8841 /****************************************************************************
8842  enumprintmonitors level 1.
8843 ****************************************************************************/
8844
8845 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8846                                         union spoolss_MonitorInfo **info_p,
8847                                         uint32_t *count)
8848 {
8849         union spoolss_MonitorInfo *info;
8850         WERROR result = WERR_OK;
8851
8852         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8853         W_ERROR_HAVE_NO_MEMORY(info);
8854
8855         *count = 2;
8856
8857         result = fill_monitor_1(info, &info[0].info1,
8858                                 SPL_LOCAL_PORT);
8859         if (!W_ERROR_IS_OK(result)) {
8860                 goto out;
8861         }
8862
8863         result = fill_monitor_1(info, &info[1].info1,
8864                                 SPL_TCPIP_PORT);
8865         if (!W_ERROR_IS_OK(result)) {
8866                 goto out;
8867         }
8868
8869 out:
8870         if (!W_ERROR_IS_OK(result)) {
8871                 TALLOC_FREE(info);
8872                 *count = 0;
8873                 return result;
8874         }
8875
8876         *info_p = info;
8877
8878         return WERR_OK;
8879 }
8880
8881 /****************************************************************************
8882  enumprintmonitors level 2.
8883 ****************************************************************************/
8884
8885 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8886                                         union spoolss_MonitorInfo **info_p,
8887                                         uint32_t *count)
8888 {
8889         union spoolss_MonitorInfo *info;
8890         WERROR result = WERR_OK;
8891
8892         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8893         W_ERROR_HAVE_NO_MEMORY(info);
8894
8895         *count = 2;
8896
8897         result = fill_monitor_2(info, &info[0].info2,
8898                                 SPL_LOCAL_PORT,
8899                                 "Windows NT X86", /* FIXME */
8900                                 "localmon.dll");
8901         if (!W_ERROR_IS_OK(result)) {
8902                 goto out;
8903         }
8904
8905         result = fill_monitor_2(info, &info[1].info2,
8906                                 SPL_TCPIP_PORT,
8907                                 "Windows NT X86", /* FIXME */
8908                                 "tcpmon.dll");
8909         if (!W_ERROR_IS_OK(result)) {
8910                 goto out;
8911         }
8912
8913 out:
8914         if (!W_ERROR_IS_OK(result)) {
8915                 TALLOC_FREE(info);
8916                 *count = 0;
8917                 return result;
8918         }
8919
8920         *info_p = info;
8921
8922         return WERR_OK;
8923 }
8924
8925 /****************************************************************
8926  _spoolss_EnumMonitors
8927 ****************************************************************/
8928
8929 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
8930                              struct spoolss_EnumMonitors *r)
8931 {
8932         WERROR result;
8933
8934         /* that's an [in out] buffer */
8935
8936         if (!r->in.buffer && (r->in.offered != 0)) {
8937                 return WERR_INVALID_PARAM;
8938         }
8939
8940         DEBUG(5,("_spoolss_EnumMonitors\n"));
8941
8942         /*
8943          * Enumerate the print monitors ...
8944          *
8945          * Just reply with "Local Port", to keep NT happy
8946          * and I can use my nice printer checker.
8947          */
8948
8949         *r->out.count = 0;
8950         *r->out.needed = 0;
8951         *r->out.info = NULL;
8952
8953         switch (r->in.level) {
8954         case 1:
8955                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8956                                                    r->out.count);
8957                 break;
8958         case 2:
8959                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8960                                                    r->out.count);
8961                 break;
8962         default:
8963                 return WERR_UNKNOWN_LEVEL;
8964         }
8965
8966         if (!W_ERROR_IS_OK(result)) {
8967                 return result;
8968         }
8969
8970         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8971                                                      spoolss_EnumMonitors,
8972                                                      *r->out.info, r->in.level,
8973                                                      *r->out.count);
8974         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8975         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8976
8977         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8978 }
8979
8980 /****************************************************************************
8981 ****************************************************************************/
8982
8983 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8984                              const print_queue_struct *queue,
8985                              int count, int snum,
8986                              struct spoolss_PrinterInfo2 *pinfo2,
8987                              uint32_t jobid,
8988                              struct spoolss_JobInfo1 *r)
8989 {
8990         int i = 0;
8991         bool found = false;
8992
8993         for (i=0; i<count; i++) {
8994                 if (queue[i].job == (int)jobid) {
8995                         found = true;
8996                         break;
8997                 }
8998         }
8999
9000         if (found == false) {
9001                 /* NT treats not found as bad param... yet another bad choice */
9002                 return WERR_INVALID_PARAM;
9003         }
9004
9005         return fill_job_info1(mem_ctx,
9006                               r,
9007                               &queue[i],
9008                               i,
9009                               snum,
9010                               pinfo2);
9011 }
9012
9013 /****************************************************************************
9014 ****************************************************************************/
9015
9016 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9017                              const print_queue_struct *queue,
9018                              int count, int snum,
9019                              struct spoolss_PrinterInfo2 *pinfo2,
9020                              uint32_t jobid,
9021                              struct spoolss_JobInfo2 *r)
9022 {
9023         int i = 0;
9024         bool found = false;
9025         struct spoolss_DeviceMode *devmode;
9026         WERROR result;
9027
9028         for (i=0; i<count; i++) {
9029                 if (queue[i].job == (int)jobid) {
9030                         found = true;
9031                         break;
9032                 }
9033         }
9034
9035         if (found == false) {
9036                 /* NT treats not found as bad param... yet another bad
9037                    choice */
9038                 return WERR_INVALID_PARAM;
9039         }
9040
9041         /*
9042          * if the print job does not have a DEVMODE associated with it,
9043          * just use the one for the printer. A NULL devicemode is not
9044          *  a failure condition
9045          */
9046
9047         devmode = print_job_devmode(lp_const_servicename(snum), jobid);
9048         if (!devmode) {
9049                 result = spoolss_create_default_devmode(mem_ctx,
9050                                                 pinfo2->printername,
9051                                                 &devmode);
9052                 if (!W_ERROR_IS_OK(result)) {
9053                         DEBUG(3, ("Can't proceed w/o a devmode!"));
9054                         return result;
9055                 }
9056         }
9057
9058         return fill_job_info2(mem_ctx,
9059                               r,
9060                               &queue[i],
9061                               i,
9062                               snum,
9063                               pinfo2,
9064                               devmode);
9065 }
9066
9067 /****************************************************************
9068  _spoolss_GetJob
9069 ****************************************************************/
9070
9071 WERROR _spoolss_GetJob(struct pipes_struct *p,
9072                        struct spoolss_GetJob *r)
9073 {
9074         WERROR result = WERR_OK;
9075         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9076         int snum;
9077         int count;
9078         print_queue_struct      *queue = NULL;
9079         print_status_struct prt_status;
9080
9081         /* that's an [in out] buffer */
9082
9083         if (!r->in.buffer && (r->in.offered != 0)) {
9084                 return WERR_INVALID_PARAM;
9085         }
9086
9087         DEBUG(5,("_spoolss_GetJob\n"));
9088
9089         *r->out.needed = 0;
9090
9091         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9092                 return WERR_BADFID;
9093         }
9094
9095         result = winreg_get_printer(p->mem_ctx,
9096                                     get_session_info_system(),
9097                                     p->msg_ctx,
9098                                     lp_const_servicename(snum),
9099                                     &pinfo2);
9100         if (!W_ERROR_IS_OK(result)) {
9101                 return result;
9102         }
9103
9104         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9105
9106         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9107                      count, prt_status.status, prt_status.message));
9108
9109         switch (r->in.level) {
9110         case 1:
9111                 result = getjob_level_1(p->mem_ctx,
9112                                         queue, count, snum, pinfo2,
9113                                         r->in.job_id, &r->out.info->info1);
9114                 break;
9115         case 2:
9116                 result = getjob_level_2(p->mem_ctx,
9117                                         queue, count, snum, pinfo2,
9118                                         r->in.job_id, &r->out.info->info2);
9119                 break;
9120         default:
9121                 result = WERR_UNKNOWN_LEVEL;
9122                 break;
9123         }
9124
9125         SAFE_FREE(queue);
9126         TALLOC_FREE(pinfo2);
9127
9128         if (!W_ERROR_IS_OK(result)) {
9129                 TALLOC_FREE(r->out.info);
9130                 return result;
9131         }
9132
9133         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9134                                                                                    r->in.level);
9135         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9136
9137         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9138 }
9139
9140 /****************************************************************
9141  _spoolss_GetPrinterDataEx
9142 ****************************************************************/
9143
9144 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9145                                  struct spoolss_GetPrinterDataEx *r)
9146 {
9147
9148         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9149         const char *printer;
9150         int                     snum = 0;
9151         WERROR result = WERR_OK;
9152         DATA_BLOB blob;
9153         enum winreg_Type val_type;
9154         uint8_t *val_data;
9155         uint32_t val_size;
9156
9157
9158         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9159
9160         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9161                 r->in.key_name, r->in.value_name));
9162
9163         /* in case of problem, return some default values */
9164
9165         *r->out.needed  = 0;
9166         *r->out.type    = REG_NONE;
9167
9168         if (!Printer) {
9169                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9170                         OUR_HANDLE(r->in.handle)));
9171                 result = WERR_BADFID;
9172                 goto done;
9173         }
9174
9175         /* Is the handle to a printer or to the server? */
9176
9177         if (Printer->printer_type == SPLHND_SERVER) {
9178
9179                 union spoolss_PrinterData data;
9180
9181                 result = getprinterdata_printer_server(p->mem_ctx,
9182                                                        r->in.value_name,
9183                                                        r->out.type,
9184                                                        &data);
9185                 if (!W_ERROR_IS_OK(result)) {
9186                         return result;
9187                 }
9188
9189                 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
9190                                                   *r->out.type, &data);
9191                 if (!W_ERROR_IS_OK(result)) {
9192                         return result;
9193                 }
9194
9195                 *r->out.needed = blob.length;
9196
9197                 if (r->in.offered >= *r->out.needed) {
9198                         memcpy(r->out.data, blob.data, blob.length);
9199                 }
9200
9201                 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9202         }
9203
9204         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9205                 return WERR_BADFID;
9206         }
9207         printer = lp_const_servicename(snum);
9208
9209         /* check to see if the keyname is valid */
9210         if (!strlen(r->in.key_name)) {
9211                 return WERR_INVALID_PARAM;
9212         }
9213
9214         /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9215         if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9216             strequal(r->in.value_name, "ChangeId")) {
9217                 *r->out.type = REG_DWORD;
9218                 *r->out.needed = 4;
9219                 if (r->in.offered >= *r->out.needed) {
9220                         uint32_t changeid = 0;
9221
9222                         result = winreg_printer_get_changeid(p->mem_ctx,
9223                                                              get_session_info_system(),
9224                                                              p->msg_ctx,
9225                                                              printer,
9226                                                              &changeid);
9227                         if (!W_ERROR_IS_OK(result)) {
9228                                 return result;
9229                         }
9230
9231                         SIVAL(r->out.data, 0, changeid);
9232                         result = WERR_OK;
9233                 }
9234                 goto done;
9235         }
9236
9237         result = winreg_get_printer_dataex(p->mem_ctx,
9238                                            get_session_info_system(),
9239                                            p->msg_ctx,
9240                                            printer,
9241                                            r->in.key_name,
9242                                            r->in.value_name,
9243                                            &val_type,
9244                                            &val_data,
9245                                            &val_size);
9246         if (!W_ERROR_IS_OK(result)) {
9247                 return result;
9248         }
9249
9250         *r->out.needed = val_size;
9251         *r->out.type = val_type;
9252
9253         if (r->in.offered >= *r->out.needed) {
9254                 memcpy(r->out.data, val_data, val_size);
9255         }
9256
9257  done:
9258         /* retain type when returning WERR_MORE_DATA */
9259         r->out.data     = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
9260
9261         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9262 }
9263
9264 /****************************************************************
9265  _spoolss_SetPrinterDataEx
9266 ****************************************************************/
9267
9268 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9269                                  struct spoolss_SetPrinterDataEx *r)
9270 {
9271         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9272         int                     snum = 0;
9273         WERROR                  result = WERR_OK;
9274         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9275         char                    *oid_string;
9276
9277         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9278
9279         /* From MSDN documentation of SetPrinterDataEx: pass request to
9280            SetPrinterData if key is "PrinterDriverData" */
9281
9282         if (!Printer) {
9283                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9284                         OUR_HANDLE(r->in.handle)));
9285                 return WERR_BADFID;
9286         }
9287
9288         if (Printer->printer_type == SPLHND_SERVER) {
9289                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9290                         "Not implemented for server handles yet\n"));
9291                 return WERR_INVALID_PARAM;
9292         }
9293
9294         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9295                 return WERR_BADFID;
9296         }
9297
9298         /*
9299          * Access check : NT returns "access denied" if you make a
9300          * SetPrinterData call without the necessary privildge.
9301          * we were originally returning OK if nothing changed
9302          * which made Win2k issue **a lot** of SetPrinterData
9303          * when connecting to a printer  --jerry
9304          */
9305
9306         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9307                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9308                         "change denied by handle access permissions\n"));
9309                 return WERR_ACCESS_DENIED;
9310         }
9311
9312         result = winreg_get_printer(Printer,
9313                                     get_session_info_system(),
9314                                     p->msg_ctx,
9315                                     lp_servicename(snum),
9316                                     &pinfo2);
9317         if (!W_ERROR_IS_OK(result)) {
9318                 return result;
9319         }
9320
9321         /* check for OID in valuename */
9322
9323         oid_string = strchr(r->in.value_name, ',');
9324         if (oid_string) {
9325                 *oid_string = '\0';
9326                 oid_string++;
9327         }
9328
9329         /* save the registry data */
9330
9331         result = winreg_set_printer_dataex(p->mem_ctx,
9332                                            get_session_info_system(),
9333                                            p->msg_ctx,
9334                                            pinfo2->sharename,
9335                                            r->in.key_name,
9336                                            r->in.value_name,
9337                                            r->in.type,
9338                                            r->in.data,
9339                                            r->in.offered);
9340
9341         if (W_ERROR_IS_OK(result)) {
9342                 /* save the OID if one was specified */
9343                 if (oid_string) {
9344                         char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9345                                 r->in.key_name, SPOOL_OID_KEY);
9346                         if (!str) {
9347                                 result = WERR_NOMEM;
9348                                 goto done;
9349                         }
9350
9351                         /*
9352                          * I'm not checking the status here on purpose.  Don't know
9353                          * if this is right, but I'm returning the status from the
9354                          * previous set_printer_dataex() call.  I have no idea if
9355                          * this is right.    --jerry
9356                          */
9357                         winreg_set_printer_dataex(p->mem_ctx,
9358                                                   get_session_info_system(),
9359                                                   p->msg_ctx,
9360                                                   pinfo2->sharename,
9361                                                   str,
9362                                                   r->in.value_name,
9363                                                   REG_SZ,
9364                                                   (uint8_t *) oid_string,
9365                                                   strlen(oid_string) + 1);
9366                 }
9367
9368                 result = winreg_printer_update_changeid(p->mem_ctx,
9369                                                         get_session_info_system(),
9370                                                         p->msg_ctx,
9371                                                         lp_const_servicename(snum));
9372
9373         }
9374
9375 done:
9376         talloc_free(pinfo2);
9377         return result;
9378 }
9379
9380 /****************************************************************
9381  _spoolss_DeletePrinterDataEx
9382 ****************************************************************/
9383
9384 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9385                                     struct spoolss_DeletePrinterDataEx *r)
9386 {
9387         const char *printer;
9388         int             snum=0;
9389         WERROR          status = WERR_OK;
9390         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9391
9392         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9393
9394         if (!Printer) {
9395                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9396                         "Invalid handle (%s:%u:%u).\n",
9397                         OUR_HANDLE(r->in.handle)));
9398                 return WERR_BADFID;
9399         }
9400
9401         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9402                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9403                         "printer properties change denied by handle\n"));
9404                 return WERR_ACCESS_DENIED;
9405         }
9406
9407         if (!r->in.value_name || !r->in.key_name) {
9408                 return WERR_NOMEM;
9409         }
9410
9411         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9412                 return WERR_BADFID;
9413         }
9414         printer = lp_const_servicename(snum);
9415
9416         status = winreg_delete_printer_dataex(p->mem_ctx,
9417                                               get_session_info_system(),
9418                                               p->msg_ctx,
9419                                               printer,
9420                                               r->in.key_name,
9421                                               r->in.value_name);
9422         if (W_ERROR_IS_OK(status)) {
9423                 status = winreg_printer_update_changeid(p->mem_ctx,
9424                                                         get_session_info_system(),
9425                                                         p->msg_ctx,
9426                                                         printer);
9427         }
9428
9429         return status;
9430 }
9431
9432 /****************************************************************
9433  _spoolss_EnumPrinterKey
9434 ****************************************************************/
9435
9436 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9437                                struct spoolss_EnumPrinterKey *r)
9438 {
9439         uint32_t        num_keys;
9440         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9441         int             snum = 0;
9442         WERROR          result = WERR_BADFILE;
9443         const char **array = NULL;
9444         DATA_BLOB blob;
9445
9446         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9447
9448         if (!Printer) {
9449                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9450                         OUR_HANDLE(r->in.handle)));
9451                 return WERR_BADFID;
9452         }
9453
9454         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9455                 return WERR_BADFID;
9456         }
9457
9458         result = winreg_enum_printer_key(p->mem_ctx,
9459                                          get_session_info_system(),
9460                                          p->msg_ctx,
9461                                          lp_const_servicename(snum),
9462                                          r->in.key_name,
9463                                          &num_keys,
9464                                          &array);
9465         if (!W_ERROR_IS_OK(result)) {
9466                 goto done;
9467         }
9468
9469         if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9470                 result = WERR_NOMEM;
9471                 goto done;
9472         }
9473
9474         *r->out._ndr_size = r->in.offered / 2;
9475         *r->out.needed = blob.length;
9476
9477         if (r->in.offered < *r->out.needed) {
9478                 result = WERR_MORE_DATA;
9479         } else {
9480                 result = WERR_OK;
9481                 r->out.key_buffer->string_array = array;
9482         }
9483
9484  done:
9485         if (!W_ERROR_IS_OK(result)) {
9486                 TALLOC_FREE(array);
9487                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9488                         *r->out.needed = 0;
9489                 }
9490         }
9491
9492         return result;
9493 }
9494
9495 /****************************************************************
9496  _spoolss_DeletePrinterKey
9497 ****************************************************************/
9498
9499 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9500                                  struct spoolss_DeletePrinterKey *r)
9501 {
9502         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9503         int                     snum=0;
9504         WERROR                  status;
9505         const char *printer;
9506
9507         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9508
9509         if (!Printer) {
9510                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9511                         OUR_HANDLE(r->in.handle)));
9512                 return WERR_BADFID;
9513         }
9514
9515         /* if keyname == NULL, return error */
9516         if ( !r->in.key_name )
9517                 return WERR_INVALID_PARAM;
9518
9519         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9520                 return WERR_BADFID;
9521         }
9522
9523         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9524                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9525                         "printer properties change denied by handle\n"));
9526                 return WERR_ACCESS_DENIED;
9527         }
9528
9529         printer = lp_const_servicename(snum);
9530
9531         /* delete the key and all subkeys */
9532         status = winreg_delete_printer_key(p->mem_ctx,
9533                                            get_session_info_system(),
9534                                            p->msg_ctx,
9535                                            printer,
9536                                            r->in.key_name);
9537         if (W_ERROR_IS_OK(status)) {
9538                 status = winreg_printer_update_changeid(p->mem_ctx,
9539                                                         get_session_info_system(),
9540                                                         p->msg_ctx,
9541                                                         printer);
9542         }
9543
9544         return status;
9545 }
9546
9547 /****************************************************************
9548  _spoolss_EnumPrinterDataEx
9549 ****************************************************************/
9550
9551 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
9552                                   struct spoolss_EnumPrinterDataEx *r)
9553 {
9554         uint32_t        count = 0;
9555         struct spoolss_PrinterEnumValues *info = NULL;
9556         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9557         int             snum;
9558         WERROR          result;
9559
9560         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9561
9562         *r->out.count = 0;
9563         *r->out.needed = 0;
9564         *r->out.info = NULL;
9565
9566         if (!Printer) {
9567                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9568                         OUR_HANDLE(r->in.handle)));
9569                 return WERR_BADFID;
9570         }
9571
9572         /*
9573          * first check for a keyname of NULL or "".  Win2k seems to send
9574          * this a lot and we should send back WERR_INVALID_PARAM
9575          * no need to spend time looking up the printer in this case.
9576          * --jerry
9577          */
9578
9579         if (!strlen(r->in.key_name)) {
9580                 result = WERR_INVALID_PARAM;
9581                 goto done;
9582         }
9583
9584         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9585                 return WERR_BADFID;
9586         }
9587
9588         /* now look for a match on the key name */
9589         result = winreg_enum_printer_dataex(p->mem_ctx,
9590                                             get_session_info_system(),
9591                                             p->msg_ctx,
9592                                             lp_const_servicename(snum),
9593                                             r->in.key_name,
9594                                             &count,
9595                                             &info);
9596         if (!W_ERROR_IS_OK(result)) {
9597                 goto done;
9598         }
9599
9600 #if 0 /* FIXME - gd */
9601         /* housekeeping information in the reply */
9602
9603         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9604          * the hand marshalled container size is a multiple
9605          * of 4 bytes for RPC alignment.
9606          */
9607
9608         if (needed % 4) {
9609                 needed += 4-(needed % 4);
9610         }
9611 #endif
9612         *r->out.count   = count;
9613         *r->out.info    = info;
9614
9615  done:
9616         if (!W_ERROR_IS_OK(result)) {
9617                 return result;
9618         }
9619
9620         *r->out.needed  = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9621                                                spoolss_EnumPrinterDataEx,
9622                                                *r->out.info,
9623                                                *r->out.count);
9624         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9625         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9626
9627         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9628 }
9629
9630 /****************************************************************************
9631 ****************************************************************************/
9632
9633 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9634                                                  const char *servername,
9635                                                  const char *environment,
9636                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
9637 {
9638         WERROR werr;
9639         char *path = NULL;
9640
9641         werr = compose_spoolss_server_path(mem_ctx,
9642                                            servername,
9643                                            environment,
9644                                            SPOOLSS_PRTPROCS_PATH,
9645                                            &path);
9646         if (!W_ERROR_IS_OK(werr)) {
9647                 return werr;
9648         }
9649
9650         DEBUG(4,("print processor directory: [%s]\n", path));
9651
9652         r->directory_name = path;
9653
9654         return WERR_OK;
9655 }
9656
9657 /****************************************************************
9658  _spoolss_GetPrintProcessorDirectory
9659 ****************************************************************/
9660
9661 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
9662                                            struct spoolss_GetPrintProcessorDirectory *r)
9663 {
9664         WERROR result;
9665         char *prnproc_share = NULL;
9666         bool prnproc_share_exists = false;
9667         int snum;
9668
9669         /* that's an [in out] buffer */
9670
9671         if (!r->in.buffer && (r->in.offered != 0)) {
9672                 return WERR_INVALID_PARAM;
9673         }
9674
9675         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9676                 r->in.level));
9677
9678         *r->out.needed = 0;
9679
9680         /* r->in.level is ignored */
9681
9682         /* We always should reply with a local print processor directory so that
9683          * users are not forced to have a [prnproc$] share on the Samba spoolss
9684          * server, if users decide to do so, lets announce it though - Guenther */
9685
9686         snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
9687         if (!prnproc_share) {
9688                 return WERR_NOMEM;
9689         }
9690         if (snum != -1) {
9691                 prnproc_share_exists = true;
9692         }
9693
9694         result = getprintprocessordirectory_level_1(p->mem_ctx,
9695                                                     prnproc_share_exists ? r->in.server : NULL,
9696                                                     r->in.environment,
9697                                                     &r->out.info->info1);
9698         if (!W_ERROR_IS_OK(result)) {
9699                 TALLOC_FREE(r->out.info);
9700                 return result;
9701         }
9702
9703         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
9704                                                                                    r->out.info, r->in.level);
9705         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9706
9707         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9708 }
9709
9710 /*******************************************************************
9711  ********************************************************************/
9712
9713 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9714                                const char *dllname)
9715 {
9716         enum ndr_err_code ndr_err;
9717         struct spoolss_MonitorUi ui;
9718
9719         ui.dll_name = dllname;
9720
9721         ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
9722                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9723         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9724                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9725         }
9726         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9727 }
9728
9729 /*******************************************************************
9730  Streams the monitor UI DLL name in UNICODE
9731 *******************************************************************/
9732
9733 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9734                                struct security_token *token, DATA_BLOB *in,
9735                                DATA_BLOB *out, uint32_t *needed)
9736 {
9737         const char *dllname = "tcpmonui.dll";
9738
9739         *needed = (strlen(dllname)+1) * 2;
9740
9741         if (out->length < *needed) {
9742                 return WERR_INSUFFICIENT_BUFFER;
9743         }
9744
9745         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9746                 return WERR_NOMEM;
9747         }
9748
9749         return WERR_OK;
9750 }
9751
9752 /*******************************************************************
9753  ********************************************************************/
9754
9755 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9756                              struct spoolss_PortData1 *port1,
9757                              const DATA_BLOB *buf)
9758 {
9759         enum ndr_err_code ndr_err;
9760         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
9761                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9762         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9763                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9764         }
9765         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9766 }
9767
9768 /*******************************************************************
9769  ********************************************************************/
9770
9771 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9772                              struct spoolss_PortData2 *port2,
9773                              const DATA_BLOB *buf)
9774 {
9775         enum ndr_err_code ndr_err;
9776         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
9777                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9778         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9779                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9780         }
9781         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9782 }
9783
9784 /*******************************************************************
9785  Create a new TCP/IP port
9786 *******************************************************************/
9787
9788 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9789                              struct security_token *token, DATA_BLOB *in,
9790                              DATA_BLOB *out, uint32_t *needed)
9791 {
9792         struct spoolss_PortData1 port1;
9793         struct spoolss_PortData2 port2;
9794         char *device_uri = NULL;
9795         uint32_t version;
9796
9797         const char *portname;
9798         const char *hostaddress;
9799         const char *queue;
9800         uint32_t port_number;
9801         uint32_t protocol;
9802
9803         /* peek for spoolss_PortData version */
9804
9805         if (!in || (in->length < (128 + 4))) {
9806                 return WERR_GENERAL_FAILURE;
9807         }
9808
9809         version = IVAL(in->data, 128);
9810
9811         switch (version) {
9812                 case 1:
9813                         ZERO_STRUCT(port1);
9814
9815                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
9816                                 return WERR_NOMEM;
9817                         }
9818
9819                         portname        = port1.portname;
9820                         hostaddress     = port1.hostaddress;
9821                         queue           = port1.queue;
9822                         protocol        = port1.protocol;
9823                         port_number     = port1.port_number;
9824
9825                         break;
9826                 case 2:
9827                         ZERO_STRUCT(port2);
9828
9829                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
9830                                 return WERR_NOMEM;
9831                         }
9832
9833                         portname        = port2.portname;
9834                         hostaddress     = port2.hostaddress;
9835                         queue           = port2.queue;
9836                         protocol        = port2.protocol;
9837                         port_number     = port2.port_number;
9838
9839                         break;
9840                 default:
9841                         DEBUG(1,("xcvtcp_addport: "
9842                                 "unknown version of port_data: %d\n", version));
9843                         return WERR_UNKNOWN_PORT;
9844         }
9845
9846         /* create the device URI and call the add_port_hook() */
9847
9848         switch (protocol) {
9849         case PROTOCOL_RAWTCP_TYPE:
9850                 device_uri = talloc_asprintf(mem_ctx,
9851                                 "socket://%s:%d/", hostaddress,
9852                                 port_number);
9853                 break;
9854
9855         case PROTOCOL_LPR_TYPE:
9856                 device_uri = talloc_asprintf(mem_ctx,
9857                         "lpr://%s/%s", hostaddress, queue );
9858                 break;
9859
9860         default:
9861                 return WERR_UNKNOWN_PORT;
9862         }
9863
9864         if (!device_uri) {
9865                 return WERR_NOMEM;
9866         }
9867
9868         return add_port_hook(mem_ctx, token, portname, device_uri);
9869 }
9870
9871 /*******************************************************************
9872 *******************************************************************/
9873
9874 struct xcv_api_table xcvtcp_cmds[] = {
9875         { "MonitorUI",  xcvtcp_monitorui },
9876         { "AddPort",    xcvtcp_addport},
9877         { NULL,         NULL }
9878 };
9879
9880 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9881                                      struct security_token *token, const char *command,
9882                                      DATA_BLOB *inbuf,
9883                                      DATA_BLOB *outbuf,
9884                                      uint32_t *needed )
9885 {
9886         int i;
9887
9888         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9889
9890         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9891                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9892                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9893         }
9894
9895         return WERR_BADFUNC;
9896 }
9897
9898 /*******************************************************************
9899 *******************************************************************/
9900 #if 0   /* don't support management using the "Local Port" monitor */
9901
9902 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9903                                  struct security_token *token, DATA_BLOB *in,
9904                                  DATA_BLOB *out, uint32_t *needed)
9905 {
9906         const char *dllname = "localui.dll";
9907
9908         *needed = (strlen(dllname)+1) * 2;
9909
9910         if (out->length < *needed) {
9911                 return WERR_INSUFFICIENT_BUFFER;
9912         }
9913
9914         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9915                 return WERR_NOMEM;
9916         }
9917
9918         return WERR_OK;
9919 }
9920
9921 /*******************************************************************
9922 *******************************************************************/
9923
9924 struct xcv_api_table xcvlocal_cmds[] = {
9925         { "MonitorUI",  xcvlocal_monitorui },
9926         { NULL,         NULL }
9927 };
9928 #else
9929 struct xcv_api_table xcvlocal_cmds[] = {
9930         { NULL,         NULL }
9931 };
9932 #endif
9933
9934
9935
9936 /*******************************************************************
9937 *******************************************************************/
9938
9939 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9940                                        struct security_token *token, const char *command,
9941                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9942                                        uint32_t *needed)
9943 {
9944         int i;
9945
9946         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9947
9948         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9949                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9950                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9951         }
9952         return WERR_BADFUNC;
9953 }
9954
9955 /****************************************************************
9956  _spoolss_XcvData
9957 ****************************************************************/
9958
9959 WERROR _spoolss_XcvData(struct pipes_struct *p,
9960                         struct spoolss_XcvData *r)
9961 {
9962         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9963         DATA_BLOB out_data = data_blob_null;
9964         WERROR werror;
9965
9966         if (!Printer) {
9967                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9968                         OUR_HANDLE(r->in.handle)));
9969                 return WERR_BADFID;
9970         }
9971
9972         /* Has to be a handle to the TCP/IP port monitor */
9973
9974         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9975                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9976                 return WERR_BADFID;
9977         }
9978
9979         /* requires administrative access to the server */
9980
9981         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9982                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9983                 return WERR_ACCESS_DENIED;
9984         }
9985
9986         /* Allocate the outgoing buffer */
9987
9988         if (r->in.out_data_size) {
9989                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9990                 if (out_data.data == NULL) {
9991                         return WERR_NOMEM;
9992                 }
9993         }
9994
9995         switch ( Printer->printer_type ) {
9996         case SPLHND_PORTMON_TCP:
9997                 werror = process_xcvtcp_command(p->mem_ctx,
9998                                                 p->session_info->security_token,
9999                                                 r->in.function_name,
10000                                                 &r->in.in_data, &out_data,
10001                                                 r->out.needed);
10002                 break;
10003         case SPLHND_PORTMON_LOCAL:
10004                 werror = process_xcvlocal_command(p->mem_ctx,
10005                                                   p->session_info->security_token,
10006                                                   r->in.function_name,
10007                                                   &r->in.in_data, &out_data,
10008                                                   r->out.needed);
10009                 break;
10010         default:
10011                 werror = WERR_INVALID_PRINT_MONITOR;
10012         }
10013
10014         if (!W_ERROR_IS_OK(werror)) {
10015                 return werror;
10016         }
10017
10018         *r->out.status_code = 0;
10019
10020         if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10021                 memcpy(r->out.out_data, out_data.data,
10022                         MIN(r->in.out_data_size, out_data.length));
10023         }
10024
10025         return WERR_OK;
10026 }
10027
10028 /****************************************************************
10029  _spoolss_AddPrintProcessor
10030 ****************************************************************/
10031
10032 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10033                                   struct spoolss_AddPrintProcessor *r)
10034 {
10035         /* for now, just indicate success and ignore the add.  We'll
10036            automatically set the winprint processor for printer
10037            entries later.  Used to debug the LexMark Optra S 1855 PCL
10038            driver --jerry */
10039
10040         return WERR_OK;
10041 }
10042
10043 /****************************************************************
10044  _spoolss_AddPort
10045 ****************************************************************/
10046
10047 WERROR _spoolss_AddPort(struct pipes_struct *p,
10048                         struct spoolss_AddPort *r)
10049 {
10050         /* do what w2k3 does */
10051
10052         return WERR_NOT_SUPPORTED;
10053 }
10054
10055 /****************************************************************
10056  _spoolss_GetPrinterDriver
10057 ****************************************************************/
10058
10059 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10060                                  struct spoolss_GetPrinterDriver *r)
10061 {
10062         p->rng_fault_state = true;
10063         return WERR_NOT_SUPPORTED;
10064 }
10065
10066 /****************************************************************
10067  _spoolss_ReadPrinter
10068 ****************************************************************/
10069
10070 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10071                             struct spoolss_ReadPrinter *r)
10072 {
10073         p->rng_fault_state = true;
10074         return WERR_NOT_SUPPORTED;
10075 }
10076
10077 /****************************************************************
10078  _spoolss_WaitForPrinterChange
10079 ****************************************************************/
10080
10081 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10082                                      struct spoolss_WaitForPrinterChange *r)
10083 {
10084         p->rng_fault_state = true;
10085         return WERR_NOT_SUPPORTED;
10086 }
10087
10088 /****************************************************************
10089  _spoolss_ConfigurePort
10090 ****************************************************************/
10091
10092 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10093                               struct spoolss_ConfigurePort *r)
10094 {
10095         p->rng_fault_state = true;
10096         return WERR_NOT_SUPPORTED;
10097 }
10098
10099 /****************************************************************
10100  _spoolss_DeletePort
10101 ****************************************************************/
10102
10103 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10104                            struct spoolss_DeletePort *r)
10105 {
10106         p->rng_fault_state = true;
10107         return WERR_NOT_SUPPORTED;
10108 }
10109
10110 /****************************************************************
10111  _spoolss_CreatePrinterIC
10112 ****************************************************************/
10113
10114 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10115                                 struct spoolss_CreatePrinterIC *r)
10116 {
10117         p->rng_fault_state = true;
10118         return WERR_NOT_SUPPORTED;
10119 }
10120
10121 /****************************************************************
10122  _spoolss_PlayGDIScriptOnPrinterIC
10123 ****************************************************************/
10124
10125 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10126                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
10127 {
10128         p->rng_fault_state = true;
10129         return WERR_NOT_SUPPORTED;
10130 }
10131
10132 /****************************************************************
10133  _spoolss_DeletePrinterIC
10134 ****************************************************************/
10135
10136 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10137                                 struct spoolss_DeletePrinterIC *r)
10138 {
10139         p->rng_fault_state = true;
10140         return WERR_NOT_SUPPORTED;
10141 }
10142
10143 /****************************************************************
10144  _spoolss_AddPrinterConnection
10145 ****************************************************************/
10146
10147 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10148                                      struct spoolss_AddPrinterConnection *r)
10149 {
10150         p->rng_fault_state = true;
10151         return WERR_NOT_SUPPORTED;
10152 }
10153
10154 /****************************************************************
10155  _spoolss_DeletePrinterConnection
10156 ****************************************************************/
10157
10158 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10159                                         struct spoolss_DeletePrinterConnection *r)
10160 {
10161         p->rng_fault_state = true;
10162         return WERR_NOT_SUPPORTED;
10163 }
10164
10165 /****************************************************************
10166  _spoolss_PrinterMessageBox
10167 ****************************************************************/
10168
10169 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10170                                   struct spoolss_PrinterMessageBox *r)
10171 {
10172         p->rng_fault_state = true;
10173         return WERR_NOT_SUPPORTED;
10174 }
10175
10176 /****************************************************************
10177  _spoolss_AddMonitor
10178 ****************************************************************/
10179
10180 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10181                            struct spoolss_AddMonitor *r)
10182 {
10183         p->rng_fault_state = true;
10184         return WERR_NOT_SUPPORTED;
10185 }
10186
10187 /****************************************************************
10188  _spoolss_DeleteMonitor
10189 ****************************************************************/
10190
10191 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10192                               struct spoolss_DeleteMonitor *r)
10193 {
10194         p->rng_fault_state = true;
10195         return WERR_NOT_SUPPORTED;
10196 }
10197
10198 /****************************************************************
10199  _spoolss_DeletePrintProcessor
10200 ****************************************************************/
10201
10202 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10203                                      struct spoolss_DeletePrintProcessor *r)
10204 {
10205         p->rng_fault_state = true;
10206         return WERR_NOT_SUPPORTED;
10207 }
10208
10209 /****************************************************************
10210  _spoolss_AddPrintProvidor
10211 ****************************************************************/
10212
10213 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10214                                  struct spoolss_AddPrintProvidor *r)
10215 {
10216         p->rng_fault_state = true;
10217         return WERR_NOT_SUPPORTED;
10218 }
10219
10220 /****************************************************************
10221  _spoolss_DeletePrintProvidor
10222 ****************************************************************/
10223
10224 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10225                                     struct spoolss_DeletePrintProvidor *r)
10226 {
10227         p->rng_fault_state = true;
10228         return WERR_NOT_SUPPORTED;
10229 }
10230
10231 /****************************************************************
10232  _spoolss_FindFirstPrinterChangeNotification
10233 ****************************************************************/
10234
10235 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10236                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
10237 {
10238         p->rng_fault_state = true;
10239         return WERR_NOT_SUPPORTED;
10240 }
10241
10242 /****************************************************************
10243  _spoolss_FindNextPrinterChangeNotification
10244 ****************************************************************/
10245
10246 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10247                                                   struct spoolss_FindNextPrinterChangeNotification *r)
10248 {
10249         p->rng_fault_state = true;
10250         return WERR_NOT_SUPPORTED;
10251 }
10252
10253 /****************************************************************
10254  _spoolss_RouterFindFirstPrinterChangeNotificationOld
10255 ****************************************************************/
10256
10257 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10258                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10259 {
10260         p->rng_fault_state = true;
10261         return WERR_NOT_SUPPORTED;
10262 }
10263
10264 /****************************************************************
10265  _spoolss_ReplyOpenPrinter
10266 ****************************************************************/
10267
10268 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10269                                  struct spoolss_ReplyOpenPrinter *r)
10270 {
10271         p->rng_fault_state = true;
10272         return WERR_NOT_SUPPORTED;
10273 }
10274
10275 /****************************************************************
10276  _spoolss_RouterReplyPrinter
10277 ****************************************************************/
10278
10279 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10280                                    struct spoolss_RouterReplyPrinter *r)
10281 {
10282         p->rng_fault_state = true;
10283         return WERR_NOT_SUPPORTED;
10284 }
10285
10286 /****************************************************************
10287  _spoolss_ReplyClosePrinter
10288 ****************************************************************/
10289
10290 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10291                                   struct spoolss_ReplyClosePrinter *r)
10292 {
10293         p->rng_fault_state = true;
10294         return WERR_NOT_SUPPORTED;
10295 }
10296
10297 /****************************************************************
10298  _spoolss_AddPortEx
10299 ****************************************************************/
10300
10301 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10302                           struct spoolss_AddPortEx *r)
10303 {
10304         p->rng_fault_state = true;
10305         return WERR_NOT_SUPPORTED;
10306 }
10307
10308 /****************************************************************
10309  _spoolss_RouterFindFirstPrinterChangeNotification
10310 ****************************************************************/
10311
10312 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10313                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10314 {
10315         p->rng_fault_state = true;
10316         return WERR_NOT_SUPPORTED;
10317 }
10318
10319 /****************************************************************
10320  _spoolss_SpoolerInit
10321 ****************************************************************/
10322
10323 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10324                             struct spoolss_SpoolerInit *r)
10325 {
10326         p->rng_fault_state = true;
10327         return WERR_NOT_SUPPORTED;
10328 }
10329
10330 /****************************************************************
10331  _spoolss_ResetPrinterEx
10332 ****************************************************************/
10333
10334 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10335                                struct spoolss_ResetPrinterEx *r)
10336 {
10337         p->rng_fault_state = true;
10338         return WERR_NOT_SUPPORTED;
10339 }
10340
10341 /****************************************************************
10342  _spoolss_RouterReplyPrinterEx
10343 ****************************************************************/
10344
10345 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10346                                      struct spoolss_RouterReplyPrinterEx *r)
10347 {
10348         p->rng_fault_state = true;
10349         return WERR_NOT_SUPPORTED;
10350 }
10351
10352 /****************************************************************
10353  _spoolss_44
10354 ****************************************************************/
10355
10356 WERROR _spoolss_44(struct pipes_struct *p,
10357                    struct spoolss_44 *r)
10358 {
10359         p->rng_fault_state = true;
10360         return WERR_NOT_SUPPORTED;
10361 }
10362
10363 /****************************************************************
10364  _spoolss_SetPort
10365 ****************************************************************/
10366
10367 WERROR _spoolss_SetPort(struct pipes_struct *p,
10368                         struct spoolss_SetPort *r)
10369 {
10370         p->rng_fault_state = true;
10371         return WERR_NOT_SUPPORTED;
10372 }
10373
10374 /****************************************************************
10375  _spoolss_4a
10376 ****************************************************************/
10377
10378 WERROR _spoolss_4a(struct pipes_struct *p,
10379                    struct spoolss_4a *r)
10380 {
10381         p->rng_fault_state = true;
10382         return WERR_NOT_SUPPORTED;
10383 }
10384
10385 /****************************************************************
10386  _spoolss_4b
10387 ****************************************************************/
10388
10389 WERROR _spoolss_4b(struct pipes_struct *p,
10390                    struct spoolss_4b *r)
10391 {
10392         p->rng_fault_state = true;
10393         return WERR_NOT_SUPPORTED;
10394 }
10395
10396 /****************************************************************
10397  _spoolss_4c
10398 ****************************************************************/
10399
10400 WERROR _spoolss_4c(struct pipes_struct *p,
10401                    struct spoolss_4c *r)
10402 {
10403         p->rng_fault_state = true;
10404         return WERR_NOT_SUPPORTED;
10405 }
10406
10407 /****************************************************************
10408  _spoolss_53
10409 ****************************************************************/
10410
10411 WERROR _spoolss_53(struct pipes_struct *p,
10412                    struct spoolss_53 *r)
10413 {
10414         p->rng_fault_state = true;
10415         return WERR_NOT_SUPPORTED;
10416 }
10417
10418 /****************************************************************
10419  _spoolss_AddPerMachineConnection
10420 ****************************************************************/
10421
10422 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
10423                                         struct spoolss_AddPerMachineConnection *r)
10424 {
10425         p->rng_fault_state = true;
10426         return WERR_NOT_SUPPORTED;
10427 }
10428
10429 /****************************************************************
10430  _spoolss_DeletePerMachineConnection
10431 ****************************************************************/
10432
10433 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
10434                                            struct spoolss_DeletePerMachineConnection *r)
10435 {
10436         p->rng_fault_state = true;
10437         return WERR_NOT_SUPPORTED;
10438 }
10439
10440 /****************************************************************
10441  _spoolss_EnumPerMachineConnections
10442 ****************************************************************/
10443
10444 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
10445                                           struct spoolss_EnumPerMachineConnections *r)
10446 {
10447         p->rng_fault_state = true;
10448         return WERR_NOT_SUPPORTED;
10449 }
10450
10451 /****************************************************************
10452  _spoolss_5a
10453 ****************************************************************/
10454
10455 WERROR _spoolss_5a(struct pipes_struct *p,
10456                    struct spoolss_5a *r)
10457 {
10458         p->rng_fault_state = true;
10459         return WERR_NOT_SUPPORTED;
10460 }
10461
10462 /****************************************************************
10463  _spoolss_5b
10464 ****************************************************************/
10465
10466 WERROR _spoolss_5b(struct pipes_struct *p,
10467                    struct spoolss_5b *r)
10468 {
10469         p->rng_fault_state = true;
10470         return WERR_NOT_SUPPORTED;
10471 }
10472
10473 /****************************************************************
10474  _spoolss_5c
10475 ****************************************************************/
10476
10477 WERROR _spoolss_5c(struct pipes_struct *p,
10478                    struct spoolss_5c *r)
10479 {
10480         p->rng_fault_state = true;
10481         return WERR_NOT_SUPPORTED;
10482 }
10483
10484 /****************************************************************
10485  _spoolss_5d
10486 ****************************************************************/
10487
10488 WERROR _spoolss_5d(struct pipes_struct *p,
10489                    struct spoolss_5d *r)
10490 {
10491         p->rng_fault_state = true;
10492         return WERR_NOT_SUPPORTED;
10493 }
10494
10495 /****************************************************************
10496  _spoolss_5e
10497 ****************************************************************/
10498
10499 WERROR _spoolss_5e(struct pipes_struct *p,
10500                    struct spoolss_5e *r)
10501 {
10502         p->rng_fault_state = true;
10503         return WERR_NOT_SUPPORTED;
10504 }
10505
10506 /****************************************************************
10507  _spoolss_5f
10508 ****************************************************************/
10509
10510 WERROR _spoolss_5f(struct pipes_struct *p,
10511                    struct spoolss_5f *r)
10512 {
10513         p->rng_fault_state = true;
10514         return WERR_NOT_SUPPORTED;
10515 }
10516
10517 /****************************************************************
10518  _spoolss_60
10519 ****************************************************************/
10520
10521 WERROR _spoolss_60(struct pipes_struct *p,
10522                    struct spoolss_60 *r)
10523 {
10524         p->rng_fault_state = true;
10525         return WERR_NOT_SUPPORTED;
10526 }
10527
10528 /****************************************************************
10529  _spoolss_61
10530 ****************************************************************/
10531
10532 WERROR _spoolss_61(struct pipes_struct *p,
10533                    struct spoolss_61 *r)
10534 {
10535         p->rng_fault_state = true;
10536         return WERR_NOT_SUPPORTED;
10537 }
10538
10539 /****************************************************************
10540  _spoolss_62
10541 ****************************************************************/
10542
10543 WERROR _spoolss_62(struct pipes_struct *p,
10544                    struct spoolss_62 *r)
10545 {
10546         p->rng_fault_state = true;
10547         return WERR_NOT_SUPPORTED;
10548 }
10549
10550 /****************************************************************
10551  _spoolss_63
10552 ****************************************************************/
10553
10554 WERROR _spoolss_63(struct pipes_struct *p,
10555                    struct spoolss_63 *r)
10556 {
10557         p->rng_fault_state = true;
10558         return WERR_NOT_SUPPORTED;
10559 }
10560
10561 /****************************************************************
10562  _spoolss_64
10563 ****************************************************************/
10564
10565 WERROR _spoolss_64(struct pipes_struct *p,
10566                    struct spoolss_64 *r)
10567 {
10568         p->rng_fault_state = true;
10569         return WERR_NOT_SUPPORTED;
10570 }
10571
10572 /****************************************************************
10573  _spoolss_65
10574 ****************************************************************/
10575
10576 WERROR _spoolss_65(struct pipes_struct *p,
10577                    struct spoolss_65 *r)
10578 {
10579         p->rng_fault_state = true;
10580         return WERR_NOT_SUPPORTED;
10581 }
10582
10583 /****************************************************************
10584  _spoolss_GetCorePrinterDrivers
10585 ****************************************************************/
10586
10587 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
10588                                       struct spoolss_GetCorePrinterDrivers *r)
10589 {
10590         p->rng_fault_state = true;
10591         return WERR_NOT_SUPPORTED;
10592 }
10593
10594 /****************************************************************
10595  _spoolss_67
10596 ****************************************************************/
10597
10598 WERROR _spoolss_67(struct pipes_struct *p,
10599                    struct spoolss_67 *r)
10600 {
10601         p->rng_fault_state = true;
10602         return WERR_NOT_SUPPORTED;
10603 }
10604
10605 /****************************************************************
10606  _spoolss_GetPrinterDriverPackagePath
10607 ****************************************************************/
10608
10609 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
10610                                             struct spoolss_GetPrinterDriverPackagePath *r)
10611 {
10612         p->rng_fault_state = true;
10613         return WERR_NOT_SUPPORTED;
10614 }
10615
10616 /****************************************************************
10617  _spoolss_69
10618 ****************************************************************/
10619
10620 WERROR _spoolss_69(struct pipes_struct *p,
10621                    struct spoolss_69 *r)
10622 {
10623         p->rng_fault_state = true;
10624         return WERR_NOT_SUPPORTED;
10625 }
10626
10627 /****************************************************************
10628  _spoolss_6a
10629 ****************************************************************/
10630
10631 WERROR _spoolss_6a(struct pipes_struct *p,
10632                    struct spoolss_6a *r)
10633 {
10634         p->rng_fault_state = true;
10635         return WERR_NOT_SUPPORTED;
10636 }
10637
10638 /****************************************************************
10639  _spoolss_6b
10640 ****************************************************************/
10641
10642 WERROR _spoolss_6b(struct pipes_struct *p,
10643                    struct spoolss_6b *r)
10644 {
10645         p->rng_fault_state = true;
10646         return WERR_NOT_SUPPORTED;
10647 }
10648
10649 /****************************************************************
10650  _spoolss_6c
10651 ****************************************************************/
10652
10653 WERROR _spoolss_6c(struct pipes_struct *p,
10654                    struct spoolss_6c *r)
10655 {
10656         p->rng_fault_state = true;
10657         return WERR_NOT_SUPPORTED;
10658 }
10659
10660 /****************************************************************
10661  _spoolss_6d
10662 ****************************************************************/
10663
10664 WERROR _spoolss_6d(struct pipes_struct *p,
10665                    struct spoolss_6d *r)
10666 {
10667         p->rng_fault_state = true;
10668         return WERR_NOT_SUPPORTED;
10669 }