s3-spoolss: Fix _spoolss_EnumPrintProcessors error handling
[mat/samba.git] / source3 / rpc_server / 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/cli_spoolss.h"
35 #include "rpc_client/init_spoolss.h"
36 #include "librpc/gen_ndr/messaging.h"
37 #include "librpc/gen_ndr/ndr_security.h"
38 #include "registry.h"
39 #include "registry/reg_objects.h"
40 #include "include/printing.h"
41 #include "secrets.h"
42 #include "../librpc/gen_ndr/netlogon.h"
43 #include "rpc_misc.h"
44
45 /* macros stolen from s4 spoolss server */
46 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
47         ((info)?ndr_size_##fn(info, level, 0):0)
48
49 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
50         ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
51
52 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
53         ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
54
55 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
56
57 #undef DBGC_CLASS
58 #define DBGC_CLASS DBGC_RPC_SRV
59
60 #ifndef MAX_OPEN_PRINTER_EXS
61 #define MAX_OPEN_PRINTER_EXS 50
62 #endif
63
64 struct notify_back_channel;
65
66 /* structure to store the printer handles */
67 /* and a reference to what it's pointing to */
68 /* and the notify info asked about */
69 /* that's the central struct */
70 struct printer_handle {
71         struct printer_handle *prev, *next;
72         bool document_started;
73         bool page_started;
74         uint32 jobid; /* jobid in printing backend */
75         int printer_type;
76         fstring servername;
77         fstring sharename;
78         uint32 type;
79         uint32 access_granted;
80         struct {
81                 uint32 flags;
82                 uint32 options;
83                 fstring localmachine;
84                 uint32 printerlocal;
85                 struct spoolss_NotifyOption *option;
86                 struct policy_handle cli_hnd;
87                 struct notify_back_channel *cli_chan;
88                 uint32 change;
89                 /* are we in a FindNextPrinterChangeNotify() call? */
90                 bool fnpcn;
91                 struct messaging_context *msg_ctx;
92         } notify;
93         struct {
94                 fstring machine;
95                 fstring user;
96         } client;
97
98         /* devmode sent in the OpenPrinter() call */
99         struct spoolss_DeviceMode *devmode;
100
101         /* TODO cache the printer info2 structure */
102         struct spoolss_PrinterInfo2 *info2;
103
104 };
105
106 static struct printer_handle *printers_list;
107
108 struct printer_session_counter {
109         struct printer_session_counter *next;
110         struct printer_session_counter *prev;
111
112         int snum;
113         uint32_t counter;
114 };
115
116 static struct printer_session_counter *counter_list;
117
118 struct notify_back_channel {
119         struct notify_back_channel *prev, *next;
120
121         /* associated client */
122         struct sockaddr_storage client_address;
123
124         /* print notify back-channel pipe handle*/
125         struct rpc_pipe_client *cli_pipe;
126         uint32_t active_connections;
127 };
128
129 static struct notify_back_channel *back_channels;
130
131 /* Map generic permissions to printer object specific permissions */
132
133 const struct standard_mapping printer_std_mapping = {
134         PRINTER_READ,
135         PRINTER_WRITE,
136         PRINTER_EXECUTE,
137         PRINTER_ALL_ACCESS
138 };
139
140 /* Map generic permissions to print server object specific permissions */
141
142 const struct standard_mapping printserver_std_mapping = {
143         SERVER_READ,
144         SERVER_WRITE,
145         SERVER_EXECUTE,
146         SERVER_ALL_ACCESS
147 };
148
149 /* API table for Xcv Monitor functions */
150
151 struct xcv_api_table {
152         const char *name;
153         WERROR(*fn) (TALLOC_CTX *mem_ctx, struct security_token *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
154 };
155
156 static void prune_printername_cache(void);
157
158 /********************************************************************
159  * Canonicalize servername.
160  ********************************************************************/
161
162 static const char *canon_servername(const char *servername)
163 {
164         const char *pservername = servername;
165         while (*pservername == '\\') {
166                 pservername++;
167         }
168         return pservername;
169 }
170
171 /* translate between internal status numbers and NT status numbers */
172 static int nt_printj_status(int v)
173 {
174         switch (v) {
175         case LPQ_QUEUED:
176                 return 0;
177         case LPQ_PAUSED:
178                 return JOB_STATUS_PAUSED;
179         case LPQ_SPOOLING:
180                 return JOB_STATUS_SPOOLING;
181         case LPQ_PRINTING:
182                 return JOB_STATUS_PRINTING;
183         case LPQ_ERROR:
184                 return JOB_STATUS_ERROR;
185         case LPQ_DELETING:
186                 return JOB_STATUS_DELETING;
187         case LPQ_OFFLINE:
188                 return JOB_STATUS_OFFLINE;
189         case LPQ_PAPEROUT:
190                 return JOB_STATUS_PAPEROUT;
191         case LPQ_PRINTED:
192                 return JOB_STATUS_PRINTED;
193         case LPQ_DELETED:
194                 return JOB_STATUS_DELETED;
195         case LPQ_BLOCKED:
196                 return JOB_STATUS_BLOCKED_DEVQ;
197         case LPQ_USER_INTERVENTION:
198                 return JOB_STATUS_USER_INTERVENTION;
199         }
200         return 0;
201 }
202
203 static int nt_printq_status(int v)
204 {
205         switch (v) {
206         case LPQ_PAUSED:
207                 return PRINTER_STATUS_PAUSED;
208         case LPQ_QUEUED:
209         case LPQ_SPOOLING:
210         case LPQ_PRINTING:
211                 return 0;
212         }
213         return 0;
214 }
215
216 /***************************************************************************
217  Disconnect from the client
218 ****************************************************************************/
219
220 static void srv_spoolss_replycloseprinter(int snum,
221                                           struct printer_handle *prn_hnd)
222 {
223         WERROR result;
224         NTSTATUS status;
225
226         /*
227          * Tell the specific printing tdb we no longer want messages for this printer
228          * by deregistering our PID.
229          */
230
231         if (!print_notify_deregister_pid(snum)) {
232                 DEBUG(0, ("Failed to register our pid for printer %s\n",
233                           lp_const_servicename(snum)));
234         }
235
236         /* weird if the test succeeds !!! */
237         if (prn_hnd->notify.cli_chan == NULL ||
238             prn_hnd->notify.cli_chan->active_connections == 0) {
239                 DEBUG(0, ("Trying to close unexisting backchannel!\n"));
240                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
241                 TALLOC_FREE(prn_hnd->notify.cli_chan);
242                 return;
243         }
244
245         status = rpccli_spoolss_ReplyClosePrinter(
246                                         prn_hnd->notify.cli_chan->cli_pipe,
247                                         talloc_tos(),
248                                         &prn_hnd->notify.cli_hnd,
249                                         &result);
250         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
251                 DEBUG(0, ("reply_close_printer failed [%s].\n",
252                           win_errstr(result)));
253         }
254
255         /* if it's the last connection, deconnect the IPC$ share */
256         if (prn_hnd->notify.cli_chan->active_connections == 1) {
257
258                 cli_shutdown(rpc_pipe_np_smb_conn(prn_hnd->notify.cli_chan->cli_pipe));
259                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
260                 TALLOC_FREE(prn_hnd->notify.cli_chan);
261
262                 if (prn_hnd->notify.msg_ctx != NULL) {
263                         messaging_deregister(prn_hnd->notify.msg_ctx,
264                                              MSG_PRINTER_NOTIFY2, NULL);
265
266                         /*
267                          * Tell the serverid.tdb we're no longer
268                          * interested in printer notify messages.
269                          */
270
271                         serverid_register_msg_flags(
272                                 messaging_server_id(prn_hnd->notify.msg_ctx),
273                                 false, FLAG_MSG_PRINT_NOTIFY);
274                 }
275         }
276
277         if (prn_hnd->notify.cli_chan) {
278                 prn_hnd->notify.cli_chan->active_connections--;
279         }
280 }
281
282 /****************************************************************************
283  Functions to free a printer entry datastruct.
284 ****************************************************************************/
285
286 static int printer_entry_destructor(struct printer_handle *Printer)
287 {
288         if (Printer->notify.cli_chan != NULL &&
289             Printer->notify.cli_chan->active_connections > 0) {
290                 int snum = -1;
291
292                 switch(Printer->printer_type) {
293                 case SPLHND_SERVER:
294                         srv_spoolss_replycloseprinter(snum, Printer);
295                         break;
296
297                 case SPLHND_PRINTER:
298                         snum = print_queue_snum(Printer->sharename);
299                         if (snum != -1) {
300                                 srv_spoolss_replycloseprinter(snum, Printer);
301                         }
302                         break;
303                 default:
304                         break;
305                 }
306         }
307
308         Printer->notify.flags=0;
309         Printer->notify.options=0;
310         Printer->notify.localmachine[0]='\0';
311         Printer->notify.printerlocal=0;
312         TALLOC_FREE(Printer->notify.option);
313         TALLOC_FREE(Printer->devmode);
314
315         /* Remove from the internal list. */
316         DLIST_REMOVE(printers_list, Printer);
317         return 0;
318 }
319
320 /****************************************************************************
321   find printer index by handle
322 ****************************************************************************/
323
324 static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
325                                                         struct policy_handle *hnd)
326 {
327         struct printer_handle *find_printer = NULL;
328
329         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
330                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
331                 return NULL;
332         }
333
334         return find_printer;
335 }
336
337 /****************************************************************************
338  Close printer index by handle.
339 ****************************************************************************/
340
341 static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
342 {
343         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
344
345         if (!Printer) {
346                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
347                         OUR_HANDLE(hnd)));
348                 return false;
349         }
350
351         close_policy_hnd(p, hnd);
352
353         return true;
354 }
355
356 /****************************************************************************
357  Delete a printer given a handle.
358 ****************************************************************************/
359
360 static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
361                                   const char *sharename,
362                                   struct messaging_context *msg_ctx)
363 {
364         char *cmd = lp_deleteprinter_cmd();
365         char *command = NULL;
366         int ret;
367         bool is_print_op = false;
368
369         /* can't fail if we don't try */
370
371         if ( !*cmd )
372                 return WERR_OK;
373
374         command = talloc_asprintf(ctx,
375                         "%s \"%s\"",
376                         cmd, sharename);
377         if (!command) {
378                 return WERR_NOMEM;
379         }
380         if ( token )
381                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
382
383         DEBUG(10,("Running [%s]\n", command));
384
385         /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
386
387         if ( is_print_op )
388                 become_root();
389
390         if ( (ret = smbrun(command, NULL)) == 0 ) {
391                 /* Tell everyone we updated smb.conf. */
392                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
393         }
394
395         if ( is_print_op )
396                 unbecome_root();
397
398         /********** END SePrintOperatorPrivlege BLOCK **********/
399
400         DEBUGADD(10,("returned [%d]\n", ret));
401
402         TALLOC_FREE(command);
403
404         if (ret != 0)
405                 return WERR_BADFID; /* What to return here? */
406
407         /* go ahead and re-read the services immediately */
408         become_root();
409         reload_services(msg_ctx, -1, false);
410         unbecome_root();
411
412         if ( lp_servicenumber( sharename )  > 0 )
413                 return WERR_ACCESS_DENIED;
414
415         return WERR_OK;
416 }
417
418 /****************************************************************************
419  Delete a printer given a handle.
420 ****************************************************************************/
421
422 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
423 {
424         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
425         WERROR result;
426
427         if (!Printer) {
428                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
429                         OUR_HANDLE(hnd)));
430                 return WERR_BADFID;
431         }
432
433         /*
434          * It turns out that Windows allows delete printer on a handle
435          * opened by an admin user, then used on a pipe handle created
436          * by an anonymous user..... but they're working on security.... riiight !
437          * JRA.
438          */
439
440         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
441                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
442                 return WERR_ACCESS_DENIED;
443         }
444
445         /* this does not need a become root since the access check has been
446            done on the handle already */
447
448         result = winreg_delete_printer_key(p->mem_ctx,
449                                            get_server_info_system(),
450                                            p->msg_ctx,
451                                            Printer->sharename,
452                                            "");
453         if (!W_ERROR_IS_OK(result)) {
454                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
455                 return WERR_BADFID;
456         }
457
458         result = delete_printer_hook(p->mem_ctx, p->server_info->ptok,
459                                      Printer->sharename, p->msg_ctx);
460         if (!W_ERROR_IS_OK(result)) {
461                 return result;
462         }
463         prune_printername_cache();
464         return WERR_OK;
465 }
466
467 /****************************************************************************
468  Return the snum of a printer corresponding to an handle.
469 ****************************************************************************/
470
471 static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
472                              int *number, struct share_params **params)
473 {
474         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
475
476         if (!Printer) {
477                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
478                         OUR_HANDLE(hnd)));
479                 return false;
480         }
481
482         switch (Printer->printer_type) {
483                 case SPLHND_PRINTER:
484                         DEBUG(4,("short name:%s\n", Printer->sharename));
485                         *number = print_queue_snum(Printer->sharename);
486                         return (*number != -1);
487                 case SPLHND_SERVER:
488                         return false;
489                 default:
490                         return false;
491         }
492 }
493
494 /****************************************************************************
495  Set printer handle type.
496  Check if it's \\server or \\server\printer
497 ****************************************************************************/
498
499 static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
500 {
501         DEBUG(3,("Setting printer type=%s\n", handlename));
502
503         /* it's a print server */
504         if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
505                 DEBUGADD(4,("Printer is a print server\n"));
506                 Printer->printer_type = SPLHND_SERVER;
507         }
508         /* it's a printer (set_printer_hnd_name() will handle port monitors */
509         else {
510                 DEBUGADD(4,("Printer is a printer\n"));
511                 Printer->printer_type = SPLHND_PRINTER;
512         }
513
514         return true;
515 }
516
517 static void prune_printername_cache_fn(const char *key, const char *value,
518                                        time_t timeout, void *private_data)
519 {
520         gencache_del(key);
521 }
522
523 static void prune_printername_cache(void)
524 {
525         gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
526 }
527
528 /****************************************************************************
529  Set printer handle name..  Accept names like \\server, \\server\printer,
530  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
531  the MSDN docs regarding OpenPrinter() for details on the XcvData() and
532  XcvDataPort() interface.
533 ****************************************************************************/
534
535 static bool set_printer_hnd_name(TALLOC_CTX *mem_ctx,
536                                  const struct auth_serversupplied_info *server_info,
537                                  struct messaging_context *msg_ctx,
538                                  struct printer_handle *Printer,
539                                  const char *handlename)
540 {
541         int snum;
542         int n_services=lp_numservices();
543         char *aprinter;
544         const char *printername;
545         const char *servername = NULL;
546         fstring sname;
547         bool found = false;
548         struct spoolss_PrinterInfo2 *info2 = NULL;
549         WERROR result;
550
551         /*
552          * Hopefully nobody names his printers like this. Maybe \ or ,
553          * are illegal in printer names even?
554          */
555         const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
556         char *cache_key;
557         char *tmp;
558
559         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
560                 (unsigned long)strlen(handlename)));
561
562         aprinter = CONST_DISCARD(char *, handlename);
563         if ( *handlename == '\\' ) {
564                 servername = canon_servername(handlename);
565                 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
566                         *aprinter = '\0';
567                         aprinter++;
568                 }
569                 if (!is_myname_or_ipaddr(servername)) {
570                         return false;
571                 }
572
573                 fstrcpy(Printer->servername, servername);
574         }
575
576         if (Printer->printer_type == SPLHND_SERVER) {
577                 return true;
578         }
579
580         if (Printer->printer_type != SPLHND_PRINTER) {
581                 return false;
582         }
583
584         DEBUGADD(5, ("searching for [%s]\n", aprinter));
585
586         /* check for the Port Monitor Interface */
587         if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
588                 Printer->printer_type = SPLHND_PORTMON_TCP;
589                 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
590                 found = true;
591         }
592         else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
593                 Printer->printer_type = SPLHND_PORTMON_LOCAL;
594                 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
595                 found = true;
596         }
597
598         /*
599          * With hundreds of printers, the "for" loop iterating all
600          * shares can be quite expensive, as it is done on every
601          * OpenPrinter. The loop maps "aprinter" to "sname", the
602          * result of which we cache in gencache.
603          */
604
605         cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s",
606                                     aprinter);
607         if ((cache_key != NULL) && gencache_get(cache_key, &tmp, NULL)) {
608
609                 found = (strcmp(tmp, printer_not_found) != 0);
610                 if (!found) {
611                         DEBUG(4, ("Printer %s not found\n", aprinter));
612                         SAFE_FREE(tmp);
613                         return false;
614                 }
615                 fstrcpy(sname, tmp);
616                 SAFE_FREE(tmp);
617         }
618
619         /* Search all sharenames first as this is easier than pulling
620            the printer_info_2 off of disk. Don't use find_service() since
621            that calls out to map_username() */
622
623         /* do another loop to look for printernames */
624         for (snum = 0; !found && snum < n_services; snum++) {
625                 const char *printer = lp_const_servicename(snum);
626
627                 /* no point going on if this is not a printer */
628                 if (!(lp_snum_ok(snum) && lp_print_ok(snum))) {
629                         continue;
630                 }
631
632                 /* ignore [printers] share */
633                 if (strequal(printer, "printers")) {
634                         continue;
635                 }
636
637                 fstrcpy(sname, printer);
638                 if (strequal(aprinter, printer)) {
639                         found = true;
640                         break;
641                 }
642
643                 /* no point looking up the printer object if
644                    we aren't allowing printername != sharename */
645                 if (lp_force_printername(snum)) {
646                         continue;
647                 }
648
649                 result = winreg_get_printer(mem_ctx,
650                                             server_info,
651                                             msg_ctx,
652                                             servername,
653                                             sname,
654                                             &info2);
655                 if ( !W_ERROR_IS_OK(result) ) {
656                         DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
657                                  sname, win_errstr(result)));
658                         continue;
659                 }
660
661                 printername = strrchr(info2->printername, '\\');
662                 if (printername == NULL) {
663                         printername = info2->printername;
664                 } else {
665                         printername++;
666                 }
667
668                 if (strequal(printername, aprinter)) {
669                         found = true;
670                         break;
671                 }
672
673                 DEBUGADD(10, ("printername: %s\n", printername));
674
675                 TALLOC_FREE(info2);
676         }
677
678         if ( !found ) {
679                 if (cache_key != NULL) {
680                         gencache_set(cache_key, printer_not_found,
681                                      time(NULL)+300);
682                         TALLOC_FREE(cache_key);
683                 }
684                 DEBUGADD(4,("Printer not found\n"));
685                 return false;
686         }
687
688         if (cache_key != NULL) {
689                 gencache_set(cache_key, sname, time(NULL)+300);
690                 TALLOC_FREE(cache_key);
691         }
692
693         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
694
695         fstrcpy(Printer->sharename, sname);
696
697         return true;
698 }
699
700 /****************************************************************************
701  Find first available printer slot. creates a printer handle for you.
702  ****************************************************************************/
703
704 static bool open_printer_hnd(struct pipes_struct *p, struct policy_handle *hnd,
705                              const char *name, uint32_t access_granted)
706 {
707         struct printer_handle *new_printer;
708
709         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
710
711         new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
712         if (new_printer == NULL) {
713                 return false;
714         }
715         talloc_set_destructor(new_printer, printer_entry_destructor);
716
717         /* This also steals the printer_handle on the policy_handle */
718         if (!create_policy_hnd(p, hnd, new_printer)) {
719                 TALLOC_FREE(new_printer);
720                 return false;
721         }
722
723         /* Add to the internal list. */
724         DLIST_ADD(printers_list, new_printer);
725
726         new_printer->notify.option=NULL;
727
728         if (!set_printer_hnd_printertype(new_printer, name)) {
729                 close_printer_handle(p, hnd);
730                 return false;
731         }
732
733         if (!set_printer_hnd_name(p->mem_ctx,
734                                   get_server_info_system(),
735                                   p->msg_ctx,
736                                   new_printer, name)) {
737                 close_printer_handle(p, hnd);
738                 return false;
739         }
740
741         new_printer->access_granted = access_granted;
742
743         DEBUG(5, ("%d printer handles active\n",
744                   (int)num_pipe_handles(p)));
745
746         return true;
747 }
748
749 /***************************************************************************
750  check to see if the client motify handle is monitoring the notification
751  given by (notify_type, notify_field).
752  **************************************************************************/
753
754 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
755                                       uint16_t notify_field)
756 {
757         return true;
758 }
759
760 static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
761                                 uint16_t notify_field)
762 {
763         struct spoolss_NotifyOption *option = p->notify.option;
764         uint32_t i, j;
765
766         /*
767          * Flags should always be zero when the change notify
768          * is registered by the client's spooler.  A user Win32 app
769          * might use the flags though instead of the NOTIFY_OPTION_INFO
770          * --jerry
771          */
772
773         if (!option) {
774                 return false;
775         }
776
777         if (p->notify.flags)
778                 return is_monitoring_event_flags(
779                         p->notify.flags, notify_type, notify_field);
780
781         for (i = 0; i < option->count; i++) {
782
783                 /* Check match for notify_type */
784
785                 if (option->types[i].type != notify_type)
786                         continue;
787
788                 /* Check match for field */
789
790                 for (j = 0; j < option->types[i].count; j++) {
791                         if (option->types[i].fields[j].field == notify_field) {
792                                 return true;
793                         }
794                 }
795         }
796
797         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
798                    p->servername, p->sharename, notify_type, notify_field));
799
800         return false;
801 }
802
803 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
804         _data->data.integer[0] = _integer; \
805         _data->data.integer[1] = 0;
806
807
808 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
809         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
810         if (!_data->data.string.string) {\
811                 _data->data.string.size = 0; \
812         } \
813         _data->data.string.size = strlen_m_term(_p) * 2;
814
815 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
816         _data->data.devmode.devmode = _devmode;
817
818 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
819         _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
820         if (!_data->data.sd.sd) { \
821                 _data->data.sd.sd_size = 0; \
822         } \
823         _data->data.sd.sd_size = \
824                 ndr_size_security_descriptor(_data->data.sd.sd, 0);
825
826 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
827                                    struct tm *t,
828                                    const char **pp,
829                                    uint32_t *plen)
830 {
831         struct spoolss_Time st;
832         uint32_t len = 16;
833         char *p;
834
835         if (!init_systemtime(&st, t)) {
836                 return;
837         }
838
839         p = talloc_array(mem_ctx, char, len);
840         if (!p) {
841                 return;
842         }
843
844         /*
845          * Systemtime must be linearized as a set of UINT16's.
846          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
847          */
848
849         SSVAL(p, 0, st.year);
850         SSVAL(p, 2, st.month);
851         SSVAL(p, 4, st.day_of_week);
852         SSVAL(p, 6, st.day);
853         SSVAL(p, 8, st.hour);
854         SSVAL(p, 10, st.minute);
855         SSVAL(p, 12, st.second);
856         SSVAL(p, 14, st.millisecond);
857
858         *pp = p;
859         *plen = len;
860 }
861
862 /* Convert a notification message to a struct spoolss_Notify */
863
864 static void notify_one_value(struct spoolss_notify_msg *msg,
865                              struct spoolss_Notify *data,
866                              TALLOC_CTX *mem_ctx)
867 {
868         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
869 }
870
871 static void notify_string(struct spoolss_notify_msg *msg,
872                           struct spoolss_Notify *data,
873                           TALLOC_CTX *mem_ctx)
874 {
875         /* The length of the message includes the trailing \0 */
876
877         data->data.string.size = msg->len * 2;
878         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
879         if (!data->data.string.string) {
880                 data->data.string.size = 0;
881                 return;
882         }
883 }
884
885 static void notify_system_time(struct spoolss_notify_msg *msg,
886                                struct spoolss_Notify *data,
887                                TALLOC_CTX *mem_ctx)
888 {
889         data->data.string.string = NULL;
890         data->data.string.size = 0;
891
892         if (msg->len != sizeof(time_t)) {
893                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
894                           msg->len));
895                 return;
896         }
897
898         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
899                                &data->data.string.string,
900                                &data->data.string.size);
901 }
902
903 struct notify2_message_table {
904         const char *name;
905         void (*fn)(struct spoolss_notify_msg *msg,
906                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
907 };
908
909 static struct notify2_message_table printer_notify_table[] = {
910         /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
911         /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
912         /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
913         /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
914         /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
915         /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
916         /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
917         /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
918         /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
919         /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
920         /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
921         /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
922         /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
923         /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
924         /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
925         /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
926         /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
927         /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
928         /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
929 };
930
931 static struct notify2_message_table job_notify_table[] = {
932         /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
933         /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
934         /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
935         /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
936         /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
937         /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
938         /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
939         /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
940         /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
941         /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
942         /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
943         /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
944         /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
945         /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
946         /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
947         /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
948         /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
949         /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
950         /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
951         /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
952         /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
953         /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
954         /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
955         /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
956 };
957
958
959 /***********************************************************************
960  Allocate talloc context for container object
961  **********************************************************************/
962
963 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
964 {
965         if ( !ctr )
966                 return;
967
968         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
969
970         return;
971 }
972
973 /***********************************************************************
974  release all allocated memory and zero out structure
975  **********************************************************************/
976
977 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
978 {
979         if ( !ctr )
980                 return;
981
982         if ( ctr->ctx )
983                 talloc_destroy(ctr->ctx);
984
985         ZERO_STRUCTP(ctr);
986
987         return;
988 }
989
990 /***********************************************************************
991  **********************************************************************/
992
993 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
994 {
995         if ( !ctr )
996                 return NULL;
997
998         return ctr->ctx;
999 }
1000
1001 /***********************************************************************
1002  **********************************************************************/
1003
1004 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1005 {
1006         if ( !ctr || !ctr->msg_groups )
1007                 return NULL;
1008
1009         if ( idx >= ctr->num_groups )
1010                 return NULL;
1011
1012         return &ctr->msg_groups[idx];
1013
1014 }
1015
1016 /***********************************************************************
1017  How many groups of change messages do we have ?
1018  **********************************************************************/
1019
1020 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1021 {
1022         if ( !ctr )
1023                 return 0;
1024
1025         return ctr->num_groups;
1026 }
1027
1028 /***********************************************************************
1029  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1030  **********************************************************************/
1031
1032 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1033 {
1034         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
1035         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
1036         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
1037         int                             i, new_slot;
1038
1039         if ( !ctr || !msg )
1040                 return 0;
1041
1042         /* loop over all groups looking for a matching printer name */
1043
1044         for ( i=0; i<ctr->num_groups; i++ ) {
1045                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1046                         break;
1047         }
1048
1049         /* add a new group? */
1050
1051         if ( i == ctr->num_groups ) {
1052                 ctr->num_groups++;
1053
1054                 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1055                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1056                         return 0;
1057                 }
1058                 ctr->msg_groups = groups;
1059
1060                 /* clear the new entry and set the printer name */
1061
1062                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1063                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1064         }
1065
1066         /* add the change messages; 'i' is the correct index now regardless */
1067
1068         msg_grp = &ctr->msg_groups[i];
1069
1070         msg_grp->num_msgs++;
1071
1072         if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1073                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1074                 return 0;
1075         }
1076         msg_grp->msgs = msg_list;
1077
1078         new_slot = msg_grp->num_msgs-1;
1079         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1080
1081         /* need to allocate own copy of data */
1082
1083         if ( msg->len != 0 )
1084                 msg_grp->msgs[new_slot].notify.data = (char *)
1085                         TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
1086
1087         return ctr->num_groups;
1088 }
1089
1090 static void construct_info_data(struct spoolss_Notify *info_data,
1091                                 enum spoolss_NotifyType type,
1092                                 uint16_t field, int id);
1093
1094 /***********************************************************************
1095  Send a change notication message on all handles which have a call
1096  back registered
1097  **********************************************************************/
1098
1099 static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1100                                   struct printer_handle *prn_hnd,
1101                                   SPOOLSS_NOTIFY_MSG *messages,
1102                                   uint32_t num_msgs,
1103                                   struct spoolss_Notify **_notifies,
1104                                   int *_count)
1105 {
1106         struct spoolss_Notify *notifies;
1107         SPOOLSS_NOTIFY_MSG *msg;
1108         int count = 0;
1109         uint32_t id;
1110         int i;
1111
1112         notifies = talloc_zero_array(mem_ctx,
1113                                      struct spoolss_Notify, num_msgs);
1114         if (!notifies) {
1115                 return ENOMEM;
1116         }
1117
1118         for (i = 0; i < num_msgs; i++) {
1119
1120                 msg = &messages[i];
1121
1122                 /* Are we monitoring this event? */
1123
1124                 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1125                         continue;
1126                 }
1127
1128                 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1129                            "for printer [%s]\n",
1130                            msg->type, msg->field, prn_hnd->sharename));
1131
1132                 /*
1133                  * if the is a printer notification handle and not a job
1134                  * notification type, then set the id to 0.
1135                  * Otherwise just use what was specified in the message.
1136                  *
1137                  * When registering change notification on a print server
1138                  * handle we always need to send back the id (snum) matching
1139                  * the printer for which the change took place.
1140                  * For change notify registered on a printer handle,
1141                  * this does not matter and the id should be 0.
1142                  *
1143                  * --jerry
1144                  */
1145
1146                 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1147                     (prn_hnd->printer_type == SPLHND_PRINTER)) {
1148                         id = 0;
1149                 } else {
1150                         id = msg->id;
1151                 }
1152
1153                 /* Convert unix jobid to smb jobid */
1154
1155                 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1156                         id = sysjob_to_jobid(msg->id);
1157
1158                         if (id == -1) {
1159                                 DEBUG(3, ("no such unix jobid %d\n",
1160                                           msg->id));
1161                                 continue;
1162                         }
1163                 }
1164
1165                 construct_info_data(&notifies[count],
1166                                     msg->type, msg->field, id);
1167
1168                 switch(msg->type) {
1169                 case PRINTER_NOTIFY_TYPE:
1170                         if (printer_notify_table[msg->field].fn) {
1171                                 printer_notify_table[msg->field].fn(msg,
1172                                                 &notifies[count], mem_ctx);
1173                         }
1174                         break;
1175
1176                 case JOB_NOTIFY_TYPE:
1177                         if (job_notify_table[msg->field].fn) {
1178                                 job_notify_table[msg->field].fn(msg,
1179                                                 &notifies[count], mem_ctx);
1180                         }
1181                         break;
1182
1183                 default:
1184                         DEBUG(5, ("Unknown notification type %d\n",
1185                                   msg->type));
1186                         continue;
1187                 }
1188
1189                 count++;
1190         }
1191
1192         *_notifies = notifies;
1193         *_count = count;
1194
1195         return 0;
1196 }
1197
1198 static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1199                                 struct printer_handle *prn_hnd,
1200                                 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1201 {
1202         struct spoolss_Notify *notifies;
1203         int count = 0;
1204         union spoolss_ReplyPrinterInfo info;
1205         struct spoolss_NotifyInfo info0;
1206         uint32_t reply_result;
1207         NTSTATUS status;
1208         WERROR werr;
1209         int ret;
1210
1211         /* Is there notification on this handle? */
1212         if (prn_hnd->notify.cli_chan == NULL ||
1213             prn_hnd->notify.cli_chan->active_connections == 0) {
1214                 return 0;
1215         }
1216
1217         DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1218                    prn_hnd->servername, prn_hnd->sharename));
1219
1220         /* For this printer? Print servers always receive notifications. */
1221         if ((prn_hnd->printer_type == SPLHND_PRINTER)  &&
1222             (!strequal(msg_group->printername, prn_hnd->sharename))) {
1223                 return 0;
1224         }
1225
1226         DEBUG(10,("Our printer\n"));
1227
1228         /* build the array of change notifications */
1229         ret = build_notify2_messages(mem_ctx, prn_hnd,
1230                                      msg_group->msgs,
1231                                      msg_group->num_msgs,
1232                                      &notifies, &count);
1233         if (ret) {
1234                 return ret;
1235         }
1236
1237         info0.version   = 0x2;
1238         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1239         info0.count     = count;
1240         info0.notifies  = notifies;
1241
1242         info.info0 = &info0;
1243
1244         status = rpccli_spoolss_RouterReplyPrinterEx(
1245                                 prn_hnd->notify.cli_chan->cli_pipe,
1246                                 mem_ctx,
1247                                 &prn_hnd->notify.cli_hnd,
1248                                 prn_hnd->notify.change, /* color */
1249                                 prn_hnd->notify.flags,
1250                                 &reply_result,
1251                                 0, /* reply_type, must be 0 */
1252                                 info, &werr);
1253         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr)) {
1254                 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1255                           "failed: %s\n",
1256                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1257                           win_errstr(werr)));
1258         }
1259         switch (reply_result) {
1260         case 0:
1261                 break;
1262         case PRINTER_NOTIFY_INFO_DISCARDED:
1263         case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1264         case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1265                 break;
1266         default:
1267                 break;
1268         }
1269
1270         return 0;
1271 }
1272
1273 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1274 {
1275         struct printer_handle    *p;
1276         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
1277         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1278         int ret;
1279
1280         if ( !msg_group ) {
1281                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1282                 return;
1283         }
1284
1285         if (!msg_group->msgs) {
1286                 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1287                 return;
1288         }
1289
1290         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1291
1292         /* loop over all printers */
1293
1294         for (p = printers_list; p; p = p->next) {
1295                 ret = send_notify2_printer(mem_ctx, p, msg_group);
1296                 if (ret) {
1297                         goto done;
1298                 }
1299         }
1300
1301 done:
1302         DEBUG(8,("send_notify2_changes: Exit...\n"));
1303         return;
1304 }
1305
1306 /***********************************************************************
1307  **********************************************************************/
1308
1309 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1310 {
1311
1312         uint32_t tv_sec, tv_usec;
1313         size_t offset = 0;
1314
1315         /* Unpack message */
1316
1317         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1318                              msg->printer);
1319
1320         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1321                                 &tv_sec, &tv_usec,
1322                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1323
1324         if (msg->len == 0)
1325                 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1326                            &msg->notify.value[0], &msg->notify.value[1]);
1327         else
1328                 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1329                            &msg->len, &msg->notify.data);
1330
1331         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1332                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1333
1334         tv->tv_sec = tv_sec;
1335         tv->tv_usec = tv_usec;
1336
1337         if (msg->len == 0)
1338                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1339                           msg->notify.value[1]));
1340         else
1341                 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1342
1343         return true;
1344 }
1345
1346 /********************************************************************
1347  Receive a notify2 message list
1348  ********************************************************************/
1349
1350 static void receive_notify2_message_list(struct messaging_context *msg,
1351                                          void *private_data,
1352                                          uint32_t msg_type,
1353                                          struct server_id server_id,
1354                                          DATA_BLOB *data)
1355 {
1356         size_t                  msg_count, i;
1357         char                    *buf = (char *)data->data;
1358         char                    *msg_ptr;
1359         size_t                  msg_len;
1360         SPOOLSS_NOTIFY_MSG      notify;
1361         SPOOLSS_NOTIFY_MSG_CTR  messages;
1362         int                     num_groups;
1363
1364         if (data->length < 4) {
1365                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1366                 return;
1367         }
1368
1369         msg_count = IVAL(buf, 0);
1370         msg_ptr = buf + 4;
1371
1372         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1373
1374         if (msg_count == 0) {
1375                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1376                 return;
1377         }
1378
1379         /* initialize the container */
1380
1381         ZERO_STRUCT( messages );
1382         notify_msg_ctr_init( &messages );
1383
1384         /*
1385          * build message groups for each printer identified
1386          * in a change_notify msg.  Remember that a PCN message
1387          * includes the handle returned for the srv_spoolss_replyopenprinter()
1388          * call.  Therefore messages are grouped according to printer handle.
1389          */
1390
1391         for ( i=0; i<msg_count; i++ ) {
1392                 struct timeval msg_tv;
1393
1394                 if (msg_ptr + 4 - buf > data->length) {
1395                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1396                         return;
1397                 }
1398
1399                 msg_len = IVAL(msg_ptr,0);
1400                 msg_ptr += 4;
1401
1402                 if (msg_ptr + msg_len - buf > data->length) {
1403                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1404                         return;
1405                 }
1406
1407                 /* unpack messages */
1408
1409                 ZERO_STRUCT( notify );
1410                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1411                 msg_ptr += msg_len;
1412
1413                 /* add to correct list in container */
1414
1415                 notify_msg_ctr_addmsg( &messages, &notify );
1416
1417                 /* free memory that might have been allocated by notify2_unpack_msg() */
1418
1419                 if ( notify.len != 0 )
1420                         SAFE_FREE( notify.notify.data );
1421         }
1422
1423         /* process each group of messages */
1424
1425         num_groups = notify_msg_ctr_numgroups( &messages );
1426         for ( i=0; i<num_groups; i++ )
1427                 send_notify2_changes( &messages, i );
1428
1429
1430         /* cleanup */
1431
1432         DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1433                 (uint32_t)msg_count ));
1434
1435         notify_msg_ctr_destroy( &messages );
1436
1437         return;
1438 }
1439
1440 /********************************************************************
1441  Send a message to ourself about new driver being installed
1442  so we can upgrade the information for each printer bound to this
1443  driver
1444  ********************************************************************/
1445
1446 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1447                                             struct messaging_context *msg_ctx)
1448 {
1449         int len = strlen(drivername);
1450
1451         if (!len)
1452                 return false;
1453
1454         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1455                 drivername));
1456
1457         messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1458                            MSG_PRINTER_DRVUPGRADE,
1459                            (uint8_t *)drivername, len+1);
1460
1461         return true;
1462 }
1463
1464 void srv_spoolss_cleanup(void)
1465 {
1466         struct printer_session_counter *session_counter;
1467
1468         for (session_counter = counter_list;
1469              session_counter != NULL;
1470              session_counter = counter_list) {
1471                 DLIST_REMOVE(counter_list, session_counter);
1472                 TALLOC_FREE(session_counter);
1473         }
1474 }
1475
1476 /**********************************************************************
1477  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1478  over all printers, upgrading ones as necessary
1479  **********************************************************************/
1480
1481 void do_drv_upgrade_printer(struct messaging_context *msg,
1482                             void *private_data,
1483                             uint32_t msg_type,
1484                             struct server_id server_id,
1485                             DATA_BLOB *data)
1486 {
1487         TALLOC_CTX *tmp_ctx;
1488         struct auth_serversupplied_info *server_info = NULL;
1489         struct spoolss_PrinterInfo2 *pinfo2;
1490         NTSTATUS status;
1491         WERROR result;
1492         const char *drivername;
1493         int snum;
1494         int n_services = lp_numservices();
1495         size_t len;
1496
1497         tmp_ctx = talloc_new(NULL);
1498         if (!tmp_ctx) return;
1499
1500         status = make_server_info_system(tmp_ctx, &server_info);
1501         if (!NT_STATUS_IS_OK(status)) {
1502                 DEBUG(0, ("do_drv_upgrade_printer: "
1503                           "Could not create system server_info\n"));
1504                 goto done;
1505         }
1506
1507         len = MIN(data->length,sizeof(drivername)-1);
1508         drivername = talloc_strndup(tmp_ctx, (const char *)data->data, len);
1509         if (!drivername) {
1510                 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1511                 goto done;
1512         }
1513
1514         DEBUG(10, ("do_drv_upgrade_printer: "
1515                    "Got message for new driver [%s]\n", drivername));
1516
1517         /* Iterate the printer list */
1518
1519         for (snum = 0; snum < n_services; snum++) {
1520                 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1521                         continue;
1522                 }
1523
1524                 result = winreg_get_printer(tmp_ctx, server_info, msg,
1525                                             NULL,
1526                                             lp_const_servicename(snum),
1527                                             &pinfo2);
1528
1529                 if (!W_ERROR_IS_OK(result)) {
1530                         continue;
1531                 }
1532
1533                 if (!pinfo2->drivername) {
1534                         continue;
1535                 }
1536
1537                 if (strcmp(drivername, pinfo2->drivername) != 0) {
1538                         continue;
1539                 }
1540
1541                 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1542
1543                 /* all we care about currently is the change_id */
1544                 result = winreg_printer_update_changeid(tmp_ctx,
1545                                                         server_info,
1546                                                         msg,
1547                                                         pinfo2->printername);
1548
1549                 if (!W_ERROR_IS_OK(result)) {
1550                         DEBUG(3, ("do_drv_upgrade_printer: "
1551                                   "Failed to update changeid [%s]\n",
1552                                   win_errstr(result)));
1553                 }
1554         }
1555
1556         /* all done */
1557 done:
1558         talloc_free(tmp_ctx);
1559 }
1560
1561 /********************************************************************
1562  Update the cache for all printq's with a registered client
1563  connection
1564  ********************************************************************/
1565
1566 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1567 {
1568         struct printer_handle *printer = printers_list;
1569         int snum;
1570
1571         /* loop through all printers and update the cache where
1572            a client is connected */
1573         while (printer) {
1574                 if ((printer->printer_type == SPLHND_PRINTER) &&
1575                     ((printer->notify.cli_chan != NULL) &&
1576                      (printer->notify.cli_chan->active_connections > 0))) {
1577                         snum = print_queue_snum(printer->sharename);
1578                         print_queue_status(msg_ctx, snum, NULL, NULL);
1579                 }
1580
1581                 printer = printer->next;
1582         }
1583
1584         return;
1585 }
1586
1587 /****************************************************************
1588  _spoolss_OpenPrinter
1589 ****************************************************************/
1590
1591 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1592                             struct spoolss_OpenPrinter *r)
1593 {
1594         struct spoolss_OpenPrinterEx e;
1595         WERROR werr;
1596
1597         ZERO_STRUCT(e.in.userlevel);
1598
1599         e.in.printername        = r->in.printername;
1600         e.in.datatype           = r->in.datatype;
1601         e.in.devmode_ctr        = r->in.devmode_ctr;
1602         e.in.access_mask        = r->in.access_mask;
1603         e.in.level              = 0;
1604
1605         e.out.handle            = r->out.handle;
1606
1607         werr = _spoolss_OpenPrinterEx(p, &e);
1608
1609         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1610                 /* OpenPrinterEx returns this for a bad
1611                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1612                  * instead.
1613                  */
1614                 werr = WERR_INVALID_PRINTER_NAME;
1615         }
1616
1617         return werr;
1618 }
1619
1620 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1621                               struct spoolss_DeviceMode *orig,
1622                               struct spoolss_DeviceMode **dest)
1623 {
1624         struct spoolss_DeviceMode *dm;
1625
1626         dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1627         if (!dm) {
1628                 return WERR_NOMEM;
1629         }
1630
1631         /* copy all values, then duplicate strings and structs */
1632         *dm = *orig;
1633
1634         dm->devicename = talloc_strdup(dm, orig->devicename);
1635         if (!dm->devicename) {
1636                 return WERR_NOMEM;
1637         }
1638         dm->formname = talloc_strdup(dm, orig->formname);
1639         if (!dm->formname) {
1640                 return WERR_NOMEM;
1641         }
1642         if (orig->driverextra_data.data) {
1643                 dm->driverextra_data.data =
1644                         (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1645                                         orig->driverextra_data.length);
1646                 if (!dm->driverextra_data.data) {
1647                         return WERR_NOMEM;
1648                 }
1649         }
1650
1651         *dest = dm;
1652         return WERR_OK;
1653 }
1654
1655 /****************************************************************
1656  _spoolss_OpenPrinterEx
1657 ****************************************************************/
1658
1659 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1660                               struct spoolss_OpenPrinterEx *r)
1661 {
1662         int snum;
1663         struct printer_handle *Printer=NULL;
1664
1665         if (!r->in.printername) {
1666                 return WERR_INVALID_PARAM;
1667         }
1668
1669         /* some sanity check because you can open a printer or a print server */
1670         /* aka: \\server\printer or \\server */
1671
1672         DEBUGADD(3,("checking name: %s\n", r->in.printername));
1673
1674         if (!open_printer_hnd(p, r->out.handle, r->in.printername, 0)) {
1675                 DEBUG(0,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1676                         "for printer %s\n", r->in.printername));
1677                 ZERO_STRUCTP(r->out.handle);
1678                 return WERR_INVALID_PARAM;
1679         }
1680
1681         Printer = find_printer_index_by_hnd(p, r->out.handle);
1682         if ( !Printer ) {
1683                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1684                         "handle we created for printer %s\n", r->in.printername));
1685                 close_printer_handle(p, r->out.handle);
1686                 ZERO_STRUCTP(r->out.handle);
1687                 return WERR_INVALID_PARAM;
1688         }
1689
1690         /*
1691          * First case: the user is opening the print server:
1692          *
1693          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1694          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1695          *
1696          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1697          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1698          * or if the user is listed in the smb.conf printer admin parameter.
1699          *
1700          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1701          * client view printer folder, but does not show the MSAPW.
1702          *
1703          * Note: this test needs code to check access rights here too. Jeremy
1704          * could you look at this?
1705          *
1706          * Second case: the user is opening a printer:
1707          * NT doesn't let us connect to a printer if the connecting user
1708          * doesn't have print permission.
1709          *
1710          * Third case: user is opening a Port Monitor
1711          * access checks same as opening a handle to the print server.
1712          */
1713
1714         switch (Printer->printer_type )
1715         {
1716         case SPLHND_SERVER:
1717         case SPLHND_PORTMON_TCP:
1718         case SPLHND_PORTMON_LOCAL:
1719                 /* Printserver handles use global struct... */
1720
1721                 snum = -1;
1722
1723                 /* Map standard access rights to object specific access rights */
1724
1725                 se_map_standard(&r->in.access_mask,
1726                                 &printserver_std_mapping);
1727
1728                 /* Deny any object specific bits that don't apply to print
1729                    servers (i.e printer and job specific bits) */
1730
1731                 r->in.access_mask &= SEC_MASK_SPECIFIC;
1732
1733                 if (r->in.access_mask &
1734                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1735                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1736                         close_printer_handle(p, r->out.handle);
1737                         ZERO_STRUCTP(r->out.handle);
1738                         return WERR_ACCESS_DENIED;
1739                 }
1740
1741                 /* Allow admin access */
1742
1743                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1744                 {
1745                         if (!lp_ms_add_printer_wizard()) {
1746                                 close_printer_handle(p, r->out.handle);
1747                                 ZERO_STRUCTP(r->out.handle);
1748                                 return WERR_ACCESS_DENIED;
1749                         }
1750
1751                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1752                            and not a printer admin, then fail */
1753
1754                         if ((p->server_info->utok.uid != sec_initial_uid()) &&
1755                             !security_token_has_privilege(p->server_info->ptok, SEC_PRIV_PRINT_OPERATOR) &&
1756                             !token_contains_name_in_list(
1757                                     uidtoname(p->server_info->utok.uid),
1758                                     p->server_info->info3->base.domain.string,
1759                                     NULL,
1760                                     p->server_info->ptok,
1761                                     lp_printer_admin(snum))) {
1762                                 close_printer_handle(p, r->out.handle);
1763                                 ZERO_STRUCTP(r->out.handle);
1764                                 return WERR_ACCESS_DENIED;
1765                         }
1766
1767                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1768                 }
1769                 else
1770                 {
1771                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1772                 }
1773
1774                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1775                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1776
1777                 /* We fall through to return WERR_OK */
1778                 break;
1779
1780         case SPLHND_PRINTER:
1781                 /* NT doesn't let us connect to a printer if the connecting user
1782                    doesn't have print permission.  */
1783
1784                 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1785                         close_printer_handle(p, r->out.handle);
1786                         ZERO_STRUCTP(r->out.handle);
1787                         return WERR_BADFID;
1788                 }
1789
1790                 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1791                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1792                 }
1793
1794                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1795
1796                 /* map an empty access mask to the minimum access mask */
1797                 if (r->in.access_mask == 0x0)
1798                         r->in.access_mask = PRINTER_ACCESS_USE;
1799
1800                 /*
1801                  * If we are not serving the printer driver for this printer,
1802                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1803                  * will keep NT clients happy  --jerry
1804                  */
1805
1806                 if (lp_use_client_driver(snum)
1807                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1808                 {
1809                         r->in.access_mask = PRINTER_ACCESS_USE;
1810                 }
1811
1812                 /* check smb.conf parameters and the the sec_desc */
1813
1814                 if (!allow_access(lp_hostsdeny(snum), lp_hostsallow(snum),
1815                                   p->client_id->name, p->client_id->addr)) {
1816                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1817                         ZERO_STRUCTP(r->out.handle);
1818                         return WERR_ACCESS_DENIED;
1819                 }
1820
1821                 if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
1822                                    p->server_info->ptok, snum) ||
1823                     !print_access_check(get_server_info_system(),
1824                                         p->msg_ctx,
1825                                         snum,
1826                                         r->in.access_mask)) {
1827                         DEBUG(3, ("access DENIED for printer open\n"));
1828                         close_printer_handle(p, r->out.handle);
1829                         ZERO_STRUCTP(r->out.handle);
1830                         return WERR_ACCESS_DENIED;
1831                 }
1832
1833                 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1834                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1835                         close_printer_handle(p, r->out.handle);
1836                         ZERO_STRUCTP(r->out.handle);
1837                         return WERR_ACCESS_DENIED;
1838                 }
1839
1840                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1841                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1842                 else
1843                         r->in.access_mask = PRINTER_ACCESS_USE;
1844
1845                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1846                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1847
1848                 winreg_create_printer(p->mem_ctx,
1849                                       get_server_info_system(),
1850                                       p->msg_ctx,
1851                                       Printer->servername,
1852                                       lp_const_servicename(snum));
1853
1854                 break;
1855
1856         default:
1857                 /* sanity check to prevent programmer error */
1858                 ZERO_STRUCTP(r->out.handle);
1859                 return WERR_BADFID;
1860         }
1861
1862         Printer->access_granted = r->in.access_mask;
1863
1864         /*
1865          * If the client sent a devmode in the OpenPrinter() call, then
1866          * save it here in case we get a job submission on this handle
1867          */
1868
1869          if ((Printer->printer_type != SPLHND_SERVER) &&
1870              r->in.devmode_ctr.devmode) {
1871                 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1872                                 &Printer->devmode);
1873          }
1874
1875 #if 0   /* JERRY -- I'm doubtful this is really effective */
1876         /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1877            optimization in Windows 2000 clients  --jerry */
1878
1879         if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1880                 && (RA_WIN2K == get_remote_arch()) )
1881         {
1882                 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1883                 sys_usleep( 500000 );
1884         }
1885 #endif
1886
1887         return WERR_OK;
1888 }
1889
1890 /****************************************************************
1891  _spoolss_ClosePrinter
1892 ****************************************************************/
1893
1894 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1895                              struct spoolss_ClosePrinter *r)
1896 {
1897         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1898
1899         if (Printer && Printer->document_started) {
1900                 struct spoolss_EndDocPrinter e;
1901
1902                 e.in.handle = r->in.handle;
1903
1904                 _spoolss_EndDocPrinter(p, &e);
1905         }
1906
1907         if (!close_printer_handle(p, r->in.handle))
1908                 return WERR_BADFID;
1909
1910         /* clear the returned printer handle.  Observed behavior
1911            from Win2k server.  Don't think this really matters.
1912            Previous code just copied the value of the closed
1913            handle.    --jerry */
1914
1915         ZERO_STRUCTP(r->out.handle);
1916
1917         return WERR_OK;
1918 }
1919
1920 /****************************************************************
1921  _spoolss_DeletePrinter
1922 ****************************************************************/
1923
1924 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
1925                               struct spoolss_DeletePrinter *r)
1926 {
1927         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1928         WERROR result;
1929         int snum;
1930
1931         if (Printer && Printer->document_started) {
1932                 struct spoolss_EndDocPrinter e;
1933
1934                 e.in.handle = r->in.handle;
1935
1936                 _spoolss_EndDocPrinter(p, &e);
1937         }
1938
1939         if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
1940                 winreg_delete_printer_key(p->mem_ctx,
1941                                           get_server_info_system(),
1942                                           p->msg_ctx,
1943                                           lp_const_servicename(snum),
1944                                           "");
1945         }
1946
1947         result = delete_printer_handle(p, r->in.handle);
1948
1949         return result;
1950 }
1951
1952 /*******************************************************************
1953  * static function to lookup the version id corresponding to an
1954  * long architecture string
1955  ******************************************************************/
1956
1957 static const struct print_architecture_table_node archi_table[]= {
1958
1959         {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
1960         {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
1961         {"Windows NT R4000",     SPL_ARCH_W32MIPS,      2 },
1962         {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,     2 },
1963         {"Windows NT PowerPC",   SPL_ARCH_W32PPC,       2 },
1964         {"Windows IA64",         SPL_ARCH_IA64,         3 },
1965         {"Windows x64",          SPL_ARCH_X64,          3 },
1966         {NULL,                   "",            -1 }
1967 };
1968
1969 static int get_version_id(const char *arch)
1970 {
1971         int i;
1972
1973         for (i=0; archi_table[i].long_archi != NULL; i++)
1974         {
1975                 if (strcmp(arch, archi_table[i].long_archi) == 0)
1976                         return (archi_table[i].version);
1977         }
1978
1979         return -1;
1980 }
1981
1982 /****************************************************************
1983  _spoolss_DeletePrinterDriver
1984 ****************************************************************/
1985
1986 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
1987                                     struct spoolss_DeletePrinterDriver *r)
1988 {
1989
1990         struct spoolss_DriverInfo8 *info = NULL;
1991         struct spoolss_DriverInfo8 *info_win2k = NULL;
1992         int                             version;
1993         WERROR                          status;
1994
1995         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1996            and not a printer admin, then fail */
1997
1998         if ( (p->server_info->utok.uid != sec_initial_uid())
1999              && !security_token_has_privilege(p->server_info->ptok, SEC_PRIV_PRINT_OPERATOR)
2000                 && !token_contains_name_in_list(
2001                         uidtoname(p->server_info->utok.uid),
2002                         p->server_info->info3->base.domain.string,
2003                         NULL,
2004                         p->server_info->ptok,
2005                         lp_printer_admin(-1)) )
2006         {
2007                 return WERR_ACCESS_DENIED;
2008         }
2009
2010         /* check that we have a valid driver name first */
2011
2012         if ((version = get_version_id(r->in.architecture)) == -1)
2013                 return WERR_INVALID_ENVIRONMENT;
2014
2015         status = winreg_get_driver(p->mem_ctx,
2016                                    get_server_info_system(),
2017                                    p->msg_ctx,
2018                                    r->in.architecture, r->in.driver,
2019                                    version, &info);
2020         if (!W_ERROR_IS_OK(status)) {
2021                 /* try for Win2k driver if "Windows NT x86" */
2022
2023                 if ( version == 2 ) {
2024                         version = 3;
2025
2026                         status = winreg_get_driver(p->mem_ctx,
2027                                                    get_server_info_system(),
2028                                                    p->msg_ctx,
2029                                                    r->in.architecture,
2030                                                    r->in.driver,
2031                                                    version, &info);
2032                         if (!W_ERROR_IS_OK(status)) {
2033                                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2034                                 goto done;
2035                         }
2036                 }
2037                 /* otherwise it was a failure */
2038                 else {
2039                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2040                         goto done;
2041                 }
2042
2043         }
2044
2045         if (printer_driver_in_use(p->mem_ctx,
2046                                   get_server_info_system(),
2047                                   p->msg_ctx,
2048                                   info)) {
2049                 status = WERR_PRINTER_DRIVER_IN_USE;
2050                 goto done;
2051         }
2052
2053         if (version == 2) {
2054                 status = winreg_get_driver(p->mem_ctx,
2055                                            get_server_info_system(),
2056                                            p->msg_ctx,
2057                                            r->in.architecture,
2058                                            r->in.driver, 3, &info_win2k);
2059                 if (W_ERROR_IS_OK(status)) {
2060                         /* if we get to here, we now have 2 driver info structures to remove */
2061                         /* remove the Win2k driver first*/
2062
2063                         status = winreg_del_driver(p->mem_ctx,
2064                                                    get_server_info_system(),
2065                                                    p->msg_ctx,
2066                                                    info_win2k, 3);
2067                         talloc_free(info_win2k);
2068
2069                         /* this should not have failed---if it did, report to client */
2070                         if (!W_ERROR_IS_OK(status)) {
2071                                 goto done;
2072                         }
2073                 }
2074         }
2075
2076         status = winreg_del_driver(p->mem_ctx,
2077                                    get_server_info_system(),
2078                                    p->msg_ctx,
2079                                    info, version);
2080
2081 done:
2082         talloc_free(info);
2083
2084         return status;
2085 }
2086
2087 /****************************************************************
2088  _spoolss_DeletePrinterDriverEx
2089 ****************************************************************/
2090
2091 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2092                                       struct spoolss_DeletePrinterDriverEx *r)
2093 {
2094         struct spoolss_DriverInfo8      *info = NULL;
2095         struct spoolss_DriverInfo8      *info_win2k = NULL;
2096         int                             version;
2097         bool                            delete_files;
2098         WERROR                          status;
2099
2100         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2101            and not a printer admin, then fail */
2102
2103         if ( (p->server_info->utok.uid != sec_initial_uid())
2104                 && !security_token_has_privilege(p->server_info->ptok, SEC_PRIV_PRINT_OPERATOR)
2105                 && !token_contains_name_in_list(
2106                         uidtoname(p->server_info->utok.uid),
2107                         p->server_info->info3->base.domain.string,
2108                         NULL,
2109                         p->server_info->ptok, lp_printer_admin(-1)) )
2110         {
2111                 return WERR_ACCESS_DENIED;
2112         }
2113
2114         /* check that we have a valid driver name first */
2115         if ((version = get_version_id(r->in.architecture)) == -1) {
2116                 /* this is what NT returns */
2117                 return WERR_INVALID_ENVIRONMENT;
2118         }
2119
2120         if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2121                 version = r->in.version;
2122
2123         status = winreg_get_driver(p->mem_ctx,
2124                                    get_server_info_system(),
2125                                    p->msg_ctx,
2126                                    r->in.architecture,
2127                                    r->in.driver,
2128                                    version,
2129                                    &info);
2130         if (!W_ERROR_IS_OK(status)) {
2131                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2132
2133                 /*
2134                  * if the client asked for a specific version,
2135                  * or this is something other than Windows NT x86,
2136                  * then we've failed
2137                  */
2138
2139                 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2140                         goto done;
2141
2142                 /* try for Win2k driver if "Windows NT x86" */
2143
2144                 version = 3;
2145                 status = winreg_get_driver(info,
2146                                            get_server_info_system(),
2147                                            p->msg_ctx,
2148                                            r->in.architecture,
2149                                            r->in.driver,
2150                                            version, &info);
2151                 if (!W_ERROR_IS_OK(status)) {
2152                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2153                         goto done;
2154                 }
2155         }
2156
2157         if (printer_driver_in_use(info,
2158                                   get_server_info_system(),
2159                                   p->msg_ctx,
2160                                   info)) {
2161                 status = WERR_PRINTER_DRIVER_IN_USE;
2162                 goto done;
2163         }
2164
2165         /*
2166          * we have a couple of cases to consider.
2167          * (1) Are any files in use?  If so and DPD_DELTE_ALL_FILE is set,
2168          *     then the delete should fail if **any** files overlap with
2169          *     other drivers
2170          * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2171          *     non-overlapping files
2172          * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2173          *     is set, the do not delete any files
2174          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2175          */
2176
2177         delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2178
2179         /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2180
2181         if (delete_files &&
2182             (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2183             printer_driver_files_in_use(info,
2184                                         get_server_info_system(),
2185                                         p->msg_ctx,
2186                                         info)) {
2187                 /* no idea of the correct error here */
2188                 status = WERR_ACCESS_DENIED;
2189                 goto done;
2190         }
2191
2192
2193         /* also check for W32X86/3 if necessary; maybe we already have? */
2194
2195         if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION)  ) {
2196                 status = winreg_get_driver(info,
2197                                            get_server_info_system(),
2198                                            p->msg_ctx,
2199                                            r->in.architecture,
2200                                            r->in.driver, 3, &info_win2k);
2201                 if (W_ERROR_IS_OK(status)) {
2202
2203                         if (delete_files &&
2204                             (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2205                             printer_driver_files_in_use(info,
2206                                                         get_server_info_system(),
2207                                                         p->msg_ctx,
2208                                                         info_win2k)) {
2209                                 /* no idea of the correct error here */
2210                                 talloc_free(info_win2k);
2211                                 status = WERR_ACCESS_DENIED;
2212                                 goto done;
2213                         }
2214
2215                         /* if we get to here, we now have 2 driver info structures to remove */
2216                         /* remove the Win2k driver first*/
2217
2218                         status = winreg_del_driver(info,
2219                                                    get_server_info_system(),
2220                                                    p->msg_ctx,
2221                                                    info_win2k,
2222                                                    3);
2223
2224                         /* this should not have failed---if it did, report to client */
2225
2226                         if (!W_ERROR_IS_OK(status)) {
2227                                 goto done;
2228                         }
2229
2230                         /*
2231                          * now delete any associated files if delete_files is
2232                          * true. Even if this part failes, we return succes
2233                          * because the driver doesn not exist any more
2234                          */
2235                         if (delete_files) {
2236                                 delete_driver_files(get_server_info_system(),
2237                                                     info_win2k);
2238                         }
2239                 }
2240         }
2241
2242         status = winreg_del_driver(info,
2243                                    get_server_info_system(),
2244                                    p->msg_ctx,
2245                                    info,
2246                                    version);
2247         if (!W_ERROR_IS_OK(status)) {
2248                 goto done;
2249         }
2250
2251         /*
2252          * now delete any associated files if delete_files is
2253          * true. Even if this part failes, we return succes
2254          * because the driver doesn not exist any more
2255          */
2256         if (delete_files) {
2257                 delete_driver_files(get_server_info_system(), info);
2258         }
2259
2260 done:
2261         talloc_free(info);
2262         return status;
2263 }
2264
2265
2266 /********************************************************************
2267  GetPrinterData on a printer server Handle.
2268 ********************************************************************/
2269
2270 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2271                                             const char *value,
2272                                             enum winreg_Type *type,
2273                                             union spoolss_PrinterData *data)
2274 {
2275         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2276
2277         if (!StrCaseCmp(value, "W3SvcInstalled")) {
2278                 *type = REG_DWORD;
2279                 data->value = 0x00;
2280                 return WERR_OK;
2281         }
2282
2283         if (!StrCaseCmp(value, "BeepEnabled")) {
2284                 *type = REG_DWORD;
2285                 data->value = 0x00;
2286                 return WERR_OK;
2287         }
2288
2289         if (!StrCaseCmp(value, "EventLog")) {
2290                 *type = REG_DWORD;
2291                 /* formally was 0x1b */
2292                 data->value = 0x00;
2293                 return WERR_OK;
2294         }
2295
2296         if (!StrCaseCmp(value, "NetPopup")) {
2297                 *type = REG_DWORD;
2298                 data->value = 0x00;
2299                 return WERR_OK;
2300         }
2301
2302         if (!StrCaseCmp(value, "MajorVersion")) {
2303                 *type = REG_DWORD;
2304
2305                 /* Windows NT 4.0 seems to not allow uploading of drivers
2306                    to a server that reports 0x3 as the MajorVersion.
2307                    need to investigate more how Win2k gets around this .
2308                    -- jerry */
2309
2310                 if (RA_WINNT == get_remote_arch()) {
2311                         data->value = 0x02;
2312                 } else {
2313                         data->value = 0x03;
2314                 }
2315
2316                 return WERR_OK;
2317         }
2318
2319         if (!StrCaseCmp(value, "MinorVersion")) {
2320                 *type = REG_DWORD;
2321                 data->value = 0x00;
2322                 return WERR_OK;
2323         }
2324
2325         /* REG_BINARY
2326          *  uint32_t size        = 0x114
2327          *  uint32_t major       = 5
2328          *  uint32_t minor       = [0|1]
2329          *  uint32_t build       = [2195|2600]
2330          *  extra unicode string = e.g. "Service Pack 3"
2331          */
2332         if (!StrCaseCmp(value, "OSVersion")) {
2333                 DATA_BLOB blob;
2334                 enum ndr_err_code ndr_err;
2335                 struct spoolss_OSVersion os;
2336
2337                 os.major                = 5;    /* Windows 2000 == 5.0 */
2338                 os.minor                = 0;
2339                 os.build                = 2195; /* build */
2340                 os.extra_string         = "";   /* leave extra string empty */
2341
2342                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2343                         (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2344                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2345                         return WERR_GENERAL_FAILURE;
2346                 }
2347
2348                 *type = REG_BINARY;
2349                 data->binary = blob;
2350
2351                 return WERR_OK;
2352         }
2353
2354
2355         if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2356                 *type = REG_SZ;
2357
2358                 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2359                 W_ERROR_HAVE_NO_MEMORY(data->string);
2360
2361                 return WERR_OK;
2362         }
2363
2364         if (!StrCaseCmp(value, "Architecture")) {
2365                 *type = REG_SZ;
2366                 data->string = talloc_strdup(mem_ctx,
2367                         lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2368                 W_ERROR_HAVE_NO_MEMORY(data->string);
2369
2370                 return WERR_OK;
2371         }
2372
2373         if (!StrCaseCmp(value, "DsPresent")) {
2374                 *type = REG_DWORD;
2375
2376                 /* only show the publish check box if we are a
2377                    member of a AD domain */
2378
2379                 if (lp_security() == SEC_ADS) {
2380                         data->value = 0x01;
2381                 } else {
2382                         data->value = 0x00;
2383                 }
2384                 return WERR_OK;
2385         }
2386
2387         if (!StrCaseCmp(value, "DNSMachineName")) {
2388                 const char *hostname = get_mydnsfullname();
2389
2390                 if (!hostname) {
2391                         return WERR_BADFILE;
2392                 }
2393
2394                 *type = REG_SZ;
2395                 data->string = talloc_strdup(mem_ctx, hostname);
2396                 W_ERROR_HAVE_NO_MEMORY(data->string);
2397
2398                 return WERR_OK;
2399         }
2400
2401         *type = REG_NONE;
2402
2403         return WERR_INVALID_PARAM;
2404 }
2405
2406 /****************************************************************
2407  _spoolss_GetPrinterData
2408 ****************************************************************/
2409
2410 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2411                                struct spoolss_GetPrinterData *r)
2412 {
2413         struct spoolss_GetPrinterDataEx r2;
2414
2415         r2.in.handle            = r->in.handle;
2416         r2.in.key_name          = "PrinterDriverData";
2417         r2.in.value_name        = r->in.value_name;
2418         r2.in.offered           = r->in.offered;
2419         r2.out.type             = r->out.type;
2420         r2.out.data             = r->out.data;
2421         r2.out.needed           = r->out.needed;
2422
2423         return _spoolss_GetPrinterDataEx(p, &r2);
2424 }
2425
2426 /*********************************************************
2427  Connect to the client machine.
2428 **********************************************************/
2429
2430 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2431                         struct sockaddr_storage *client_ss, const char *remote_machine)
2432 {
2433         NTSTATUS ret;
2434         struct cli_state *the_cli;
2435         struct sockaddr_storage rm_addr;
2436         char addr[INET6_ADDRSTRLEN];
2437
2438         if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2439                 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2440                         remote_machine));
2441                 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2442                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2443                         return false;
2444                 }
2445                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2446         } else {
2447                 rm_addr = *client_ss;
2448                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2449                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2450                         addr));
2451         }
2452
2453         if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2454                 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2455                         addr));
2456                 return false;
2457         }
2458
2459         /* setup the connection */
2460         ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2461                 &rm_addr, 0, "IPC$", "IPC",
2462                 "", /* username */
2463                 "", /* domain */
2464                 "", /* password */
2465                 0, lp_client_signing(), NULL );
2466
2467         if ( !NT_STATUS_IS_OK( ret ) ) {
2468                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2469                         remote_machine ));
2470                 return false;
2471         }
2472
2473         if ( the_cli->protocol != PROTOCOL_NT1 ) {
2474                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2475                 cli_shutdown(the_cli);
2476                 return false;
2477         }
2478
2479         /*
2480          * Ok - we have an anonymous connection to the IPC$ share.
2481          * Now start the NT Domain stuff :-).
2482          */
2483
2484         ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2485         if (!NT_STATUS_IS_OK(ret)) {
2486                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2487                         remote_machine, nt_errstr(ret)));
2488                 cli_shutdown(the_cli);
2489                 return false;
2490         }
2491
2492         return true;
2493 }
2494
2495 /***************************************************************************
2496  Connect to the client.
2497 ****************************************************************************/
2498
2499 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2500                                         uint32_t localprinter,
2501                                         enum winreg_Type type,
2502                                         struct policy_handle *handle,
2503                                         struct notify_back_channel **_chan,
2504                                         struct sockaddr_storage *client_ss,
2505                                         struct messaging_context *msg_ctx)
2506 {
2507         WERROR result;
2508         NTSTATUS status;
2509         struct notify_back_channel *chan;
2510
2511         for (chan = back_channels; chan; chan = chan->next) {
2512                 if (memcmp(&chan->client_address, client_ss,
2513                            sizeof(struct sockaddr_storage)) == 0) {
2514                         break;
2515                 }
2516         }
2517
2518         /*
2519          * If it's the first connection, contact the client
2520          * and connect to the IPC$ share anonymously
2521          */
2522         if (!chan) {
2523                 fstring unix_printer;
2524
2525                 /* the +2 is to strip the leading 2 backslashs */
2526                 fstrcpy(unix_printer, printer + 2);
2527
2528                 chan = talloc_zero(back_channels, struct notify_back_channel);
2529                 if (!chan) {
2530                         return false;
2531                 }
2532                 chan->client_address = *client_ss;
2533
2534                 if (!spoolss_connect_to_client(&chan->cli_pipe, client_ss, unix_printer)) {
2535                         TALLOC_FREE(chan);
2536                         return false;
2537                 }
2538
2539                 DLIST_ADD(back_channels, chan);
2540
2541                 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2542                                    receive_notify2_message_list);
2543                 /* Tell the connections db we're now interested in printer
2544                  * notify messages. */
2545                 serverid_register_msg_flags(messaging_server_id(msg_ctx),
2546                                             true, FLAG_MSG_PRINT_NOTIFY);
2547         }
2548
2549         /*
2550          * Tell the specific printing tdb we want messages for this printer
2551          * by registering our PID.
2552          */
2553
2554         if (!print_notify_register_pid(snum)) {
2555                 DEBUG(0, ("Failed to register our pid for printer %s\n",
2556                           printer));
2557         }
2558
2559         status = rpccli_spoolss_ReplyOpenPrinter(chan->cli_pipe, talloc_tos(),
2560                                                  printer,
2561                                                  localprinter,
2562                                                  type,
2563                                                  0,
2564                                                  NULL,
2565                                                  handle,
2566                                                  &result);
2567         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
2568                 DEBUG(5, ("Client RPC returned [%s]\n", win_errstr(result)));
2569         }
2570
2571         chan->active_connections++;
2572         *_chan = chan;
2573
2574         return (W_ERROR_IS_OK(result));
2575 }
2576
2577 /****************************************************************
2578  ****************************************************************/
2579
2580 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2581                                                              const struct spoolss_NotifyOption *r)
2582 {
2583         struct spoolss_NotifyOption *option;
2584         uint32_t i,k;
2585
2586         if (!r) {
2587                 return NULL;
2588         }
2589
2590         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2591         if (!option) {
2592                 return NULL;
2593         }
2594
2595         *option = *r;
2596
2597         if (!option->count) {
2598                 return option;
2599         }
2600
2601         option->types = talloc_zero_array(option,
2602                 struct spoolss_NotifyOptionType, option->count);
2603         if (!option->types) {
2604                 talloc_free(option);
2605                 return NULL;
2606         }
2607
2608         for (i=0; i < option->count; i++) {
2609                 option->types[i] = r->types[i];
2610
2611                 if (option->types[i].count) {
2612                         option->types[i].fields = talloc_zero_array(option,
2613                                 union spoolss_Field, option->types[i].count);
2614                         if (!option->types[i].fields) {
2615                                 talloc_free(option);
2616                                 return NULL;
2617                         }
2618                         for (k=0; k<option->types[i].count; k++) {
2619                                 option->types[i].fields[k] =
2620                                         r->types[i].fields[k];
2621                         }
2622                 }
2623         }
2624
2625         return option;
2626 }
2627
2628 /****************************************************************
2629  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2630  *
2631  * before replying OK: status=0 a rpc call is made to the workstation
2632  * asking ReplyOpenPrinter
2633  *
2634  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2635  * called from api_spoolss_rffpcnex
2636 ****************************************************************/
2637
2638 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2639                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2640 {
2641         int snum = -1;
2642         struct spoolss_NotifyOption *option = r->in.notify_options;
2643         struct sockaddr_storage client_ss;
2644
2645         /* store the notify value in the printer struct */
2646
2647         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2648
2649         if (!Printer) {
2650                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2651                         "Invalid handle (%s:%u:%u).\n",
2652                         OUR_HANDLE(r->in.handle)));
2653                 return WERR_BADFID;
2654         }
2655
2656         Printer->notify.flags           = r->in.flags;
2657         Printer->notify.options         = r->in.options;
2658         Printer->notify.printerlocal    = r->in.printer_local;
2659         Printer->notify.msg_ctx         = p->msg_ctx;
2660
2661         TALLOC_FREE(Printer->notify.option);
2662         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2663
2664         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2665
2666         /* Connect to the client machine and send a ReplyOpenPrinter */
2667
2668         if ( Printer->printer_type == SPLHND_SERVER)
2669                 snum = -1;
2670         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2671                         !get_printer_snum(p, r->in.handle, &snum, NULL) )
2672                 return WERR_BADFID;
2673
2674         DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2675                 "client_address is %s\n", p->client_id->addr));
2676
2677         if (!interpret_string_addr(&client_ss, p->client_id->addr,
2678                                    AI_NUMERICHOST)) {
2679                 return WERR_SERVER_UNAVAILABLE;
2680         }
2681
2682         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2683                                         Printer->notify.printerlocal, REG_SZ,
2684                                         &Printer->notify.cli_hnd,
2685                                         &Printer->notify.cli_chan,
2686                                         &client_ss, p->msg_ctx)) {
2687                 return WERR_SERVER_UNAVAILABLE;
2688         }
2689
2690         return WERR_OK;
2691 }
2692
2693 /*******************************************************************
2694  * fill a notify_info_data with the servername
2695  ********************************************************************/
2696
2697 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2698                                        int snum,
2699                                        struct spoolss_Notify *data,
2700                                        print_queue_struct *queue,
2701                                        struct spoolss_PrinterInfo2 *pinfo2,
2702                                        TALLOC_CTX *mem_ctx)
2703 {
2704         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2705 }
2706
2707 /*******************************************************************
2708  * fill a notify_info_data with the printername (not including the servername).
2709  ********************************************************************/
2710
2711 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2712                                         int snum,
2713                                         struct spoolss_Notify *data,
2714                                         print_queue_struct *queue,
2715                                         struct spoolss_PrinterInfo2 *pinfo2,
2716                                         TALLOC_CTX *mem_ctx)
2717 {
2718         /* the notify name should not contain the \\server\ part */
2719         const char *p = strrchr(pinfo2->printername, '\\');
2720
2721         if (!p) {
2722                 p = pinfo2->printername;
2723         } else {
2724                 p++;
2725         }
2726
2727         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2728 }
2729
2730 /*******************************************************************
2731  * fill a notify_info_data with the servicename
2732  ********************************************************************/
2733
2734 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2735                                       int snum,
2736                                       struct spoolss_Notify *data,
2737                                       print_queue_struct *queue,
2738                                       struct spoolss_PrinterInfo2 *pinfo2,
2739                                       TALLOC_CTX *mem_ctx)
2740 {
2741         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2742 }
2743
2744 /*******************************************************************
2745  * fill a notify_info_data with the port name
2746  ********************************************************************/
2747
2748 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2749                                      int snum,
2750                                      struct spoolss_Notify *data,
2751                                      print_queue_struct *queue,
2752                                      struct spoolss_PrinterInfo2 *pinfo2,
2753                                      TALLOC_CTX *mem_ctx)
2754 {
2755         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2756 }
2757
2758 /*******************************************************************
2759  * fill a notify_info_data with the printername
2760  * but it doesn't exist, have to see what to do
2761  ********************************************************************/
2762
2763 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2764                                        int snum,
2765                                        struct spoolss_Notify *data,
2766                                        print_queue_struct *queue,
2767                                        struct spoolss_PrinterInfo2 *pinfo2,
2768                                        TALLOC_CTX *mem_ctx)
2769 {
2770         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2771 }
2772
2773 /*******************************************************************
2774  * fill a notify_info_data with the comment
2775  ********************************************************************/
2776
2777 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2778                                    int snum,
2779                                    struct spoolss_Notify *data,
2780                                    print_queue_struct *queue,
2781                                    struct spoolss_PrinterInfo2 *pinfo2,
2782                                    TALLOC_CTX *mem_ctx)
2783 {
2784         const char *p;
2785
2786         if (*pinfo2->comment == '\0') {
2787                 p = lp_comment(snum);
2788         } else {
2789                 p = pinfo2->comment;
2790         }
2791
2792         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2793 }
2794
2795 /*******************************************************************
2796  * fill a notify_info_data with the comment
2797  * location = "Room 1, floor 2, building 3"
2798  ********************************************************************/
2799
2800 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2801                                     int snum,
2802                                     struct spoolss_Notify *data,
2803                                     print_queue_struct *queue,
2804                                     struct spoolss_PrinterInfo2 *pinfo2,
2805                                     TALLOC_CTX *mem_ctx)
2806 {
2807         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->location);
2808 }
2809
2810 /*******************************************************************
2811  * fill a notify_info_data with the device mode
2812  * jfm:xxxx don't to it for know but that's a real problem !!!
2813  ********************************************************************/
2814
2815 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2816                                    int snum,
2817                                    struct spoolss_Notify *data,
2818                                    print_queue_struct *queue,
2819                                    struct spoolss_PrinterInfo2 *pinfo2,
2820                                    TALLOC_CTX *mem_ctx)
2821 {
2822         /* for a dummy implementation we have to zero the fields */
2823         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2824 }
2825
2826 /*******************************************************************
2827  * fill a notify_info_data with the separator file name
2828  ********************************************************************/
2829
2830 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2831                                    int snum,
2832                                    struct spoolss_Notify *data,
2833                                    print_queue_struct *queue,
2834                                    struct spoolss_PrinterInfo2 *pinfo2,
2835                                    TALLOC_CTX *mem_ctx)
2836 {
2837         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2838 }
2839
2840 /*******************************************************************
2841  * fill a notify_info_data with the print processor
2842  * jfm:xxxx return always winprint to indicate we don't do anything to it
2843  ********************************************************************/
2844
2845 static void spoolss_notify_print_processor(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         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2853 }
2854
2855 /*******************************************************************
2856  * fill a notify_info_data with the print processor options
2857  * jfm:xxxx send an empty string
2858  ********************************************************************/
2859
2860 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2861                                       int snum,
2862                                       struct spoolss_Notify *data,
2863                                       print_queue_struct *queue,
2864                                       struct spoolss_PrinterInfo2 *pinfo2,
2865                                       TALLOC_CTX *mem_ctx)
2866 {
2867         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2868 }
2869
2870 /*******************************************************************
2871  * fill a notify_info_data with the data type
2872  * jfm:xxxx always send RAW as data type
2873  ********************************************************************/
2874
2875 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2876                                     int snum,
2877                                     struct spoolss_Notify *data,
2878                                     print_queue_struct *queue,
2879                                     struct spoolss_PrinterInfo2 *pinfo2,
2880                                     TALLOC_CTX *mem_ctx)
2881 {
2882         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2883 }
2884
2885 /*******************************************************************
2886  * fill a notify_info_data with the security descriptor
2887  * jfm:xxxx send an null pointer to say no security desc
2888  * have to implement security before !
2889  ********************************************************************/
2890
2891 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2892                                          int snum,
2893                                          struct spoolss_Notify *data,
2894                                          print_queue_struct *queue,
2895                                          struct spoolss_PrinterInfo2 *pinfo2,
2896                                          TALLOC_CTX *mem_ctx)
2897 {
2898         SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
2899 }
2900
2901 /*******************************************************************
2902  * fill a notify_info_data with the attributes
2903  * jfm:xxxx a samba printer is always shared
2904  ********************************************************************/
2905
2906 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2907                                       int snum,
2908                                       struct spoolss_Notify *data,
2909                                       print_queue_struct *queue,
2910                                       struct spoolss_PrinterInfo2 *pinfo2,
2911                                       TALLOC_CTX *mem_ctx)
2912 {
2913         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2914 }
2915
2916 /*******************************************************************
2917  * fill a notify_info_data with the priority
2918  ********************************************************************/
2919
2920 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
2921                                     int snum,
2922                                     struct spoolss_Notify *data,
2923                                     print_queue_struct *queue,
2924                                     struct spoolss_PrinterInfo2 *pinfo2,
2925                                     TALLOC_CTX *mem_ctx)
2926 {
2927         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
2928 }
2929
2930 /*******************************************************************
2931  * fill a notify_info_data with the default priority
2932  ********************************************************************/
2933
2934 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
2935                                             int snum,
2936                                             struct spoolss_Notify *data,
2937                                             print_queue_struct *queue,
2938                                             struct spoolss_PrinterInfo2 *pinfo2,
2939                                             TALLOC_CTX *mem_ctx)
2940 {
2941         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
2942 }
2943
2944 /*******************************************************************
2945  * fill a notify_info_data with the start time
2946  ********************************************************************/
2947
2948 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
2949                                       int snum,
2950                                       struct spoolss_Notify *data,
2951                                       print_queue_struct *queue,
2952                                       struct spoolss_PrinterInfo2 *pinfo2,
2953                                       TALLOC_CTX *mem_ctx)
2954 {
2955         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
2956 }
2957
2958 /*******************************************************************
2959  * fill a notify_info_data with the until time
2960  ********************************************************************/
2961
2962 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
2963                                       int snum,
2964                                       struct spoolss_Notify *data,
2965                                       print_queue_struct *queue,
2966                                       struct spoolss_PrinterInfo2 *pinfo2,
2967                                       TALLOC_CTX *mem_ctx)
2968 {
2969         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
2970 }
2971
2972 /*******************************************************************
2973  * fill a notify_info_data with the status
2974  ********************************************************************/
2975
2976 static void spoolss_notify_status(struct messaging_context *msg_ctx,
2977                                   int snum,
2978                                   struct spoolss_Notify *data,
2979                                   print_queue_struct *queue,
2980                                   struct spoolss_PrinterInfo2 *pinfo2,
2981                                   TALLOC_CTX *mem_ctx)
2982 {
2983         print_status_struct status;
2984
2985         print_queue_length(msg_ctx, snum, &status);
2986         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
2987 }
2988
2989 /*******************************************************************
2990  * fill a notify_info_data with the number of jobs queued
2991  ********************************************************************/
2992
2993 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
2994                                  int snum,
2995                                  struct spoolss_Notify *data,
2996                                  print_queue_struct *queue,
2997                                  struct spoolss_PrinterInfo2 *pinfo2,
2998                                  TALLOC_CTX *mem_ctx)
2999 {
3000         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3001                 data, print_queue_length(msg_ctx, snum, NULL));
3002 }
3003
3004 /*******************************************************************
3005  * fill a notify_info_data with the average ppm
3006  ********************************************************************/
3007
3008 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3009                                        int snum,
3010                                        struct spoolss_Notify *data,
3011                                        print_queue_struct *queue,
3012                                        struct spoolss_PrinterInfo2 *pinfo2,
3013                                        TALLOC_CTX *mem_ctx)
3014 {
3015         /* always respond 8 pages per minutes */
3016         /* a little hard ! */
3017         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3018 }
3019
3020 /*******************************************************************
3021  * fill a notify_info_data with username
3022  ********************************************************************/
3023
3024 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3025                                     int snum,
3026                                     struct spoolss_Notify *data,
3027                                     print_queue_struct *queue,
3028                                     struct spoolss_PrinterInfo2 *pinfo2,
3029                                     TALLOC_CTX *mem_ctx)
3030 {
3031         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3032 }
3033
3034 /*******************************************************************
3035  * fill a notify_info_data with job status
3036  ********************************************************************/
3037
3038 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3039                                       int snum,
3040                                       struct spoolss_Notify *data,
3041                                       print_queue_struct *queue,
3042                                       struct spoolss_PrinterInfo2 *pinfo2,
3043                                       TALLOC_CTX *mem_ctx)
3044 {
3045         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3046 }
3047
3048 /*******************************************************************
3049  * fill a notify_info_data with job name
3050  ********************************************************************/
3051
3052 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3053                                     int snum,
3054                                     struct spoolss_Notify *data,
3055                                     print_queue_struct *queue,
3056                                     struct spoolss_PrinterInfo2 *pinfo2,
3057                                     TALLOC_CTX *mem_ctx)
3058 {
3059         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3060 }
3061
3062 /*******************************************************************
3063  * fill a notify_info_data with job status
3064  ********************************************************************/
3065
3066 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3067                                              int snum,
3068                                              struct spoolss_Notify *data,
3069                                              print_queue_struct *queue,
3070                                              struct spoolss_PrinterInfo2 *pinfo2,
3071                                              TALLOC_CTX *mem_ctx)
3072 {
3073         /*
3074          * Now we're returning job status codes we just return a "" here. JRA.
3075          */
3076
3077         const char *p = "";
3078
3079 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3080         p = "unknown";
3081
3082         switch (queue->status) {
3083         case LPQ_QUEUED:
3084                 p = "Queued";
3085                 break;
3086         case LPQ_PAUSED:
3087                 p = "";    /* NT provides the paused string */
3088                 break;
3089         case LPQ_SPOOLING:
3090                 p = "Spooling";
3091                 break;
3092         case LPQ_PRINTING:
3093                 p = "Printing";
3094                 break;
3095         }
3096 #endif /* NO LONGER NEEDED. */
3097
3098         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3099 }
3100
3101 /*******************************************************************
3102  * fill a notify_info_data with job time
3103  ********************************************************************/
3104
3105 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3106                                     int snum,
3107                                     struct spoolss_Notify *data,
3108                                     print_queue_struct *queue,
3109                                     struct spoolss_PrinterInfo2 *pinfo2,
3110                                     TALLOC_CTX *mem_ctx)
3111 {
3112         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3113 }
3114
3115 /*******************************************************************
3116  * fill a notify_info_data with job size
3117  ********************************************************************/
3118
3119 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3120                                     int snum,
3121                                     struct spoolss_Notify *data,
3122                                     print_queue_struct *queue,
3123                                     struct spoolss_PrinterInfo2 *pinfo2,
3124                                     TALLOC_CTX *mem_ctx)
3125 {
3126         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3127 }
3128
3129 /*******************************************************************
3130  * fill a notify_info_data with page info
3131  ********************************************************************/
3132 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3133                                        int snum,
3134                                 struct spoolss_Notify *data,
3135                                 print_queue_struct *queue,
3136                                 struct spoolss_PrinterInfo2 *pinfo2,
3137                                 TALLOC_CTX *mem_ctx)
3138 {
3139         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3140 }
3141
3142 /*******************************************************************
3143  * fill a notify_info_data with pages printed info.
3144  ********************************************************************/
3145 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3146                                          int snum,
3147                                 struct spoolss_Notify *data,
3148                                 print_queue_struct *queue,
3149                                 struct spoolss_PrinterInfo2 *pinfo2,
3150                                 TALLOC_CTX *mem_ctx)
3151 {
3152         /* Add code when back-end tracks this */
3153         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3154 }
3155
3156 /*******************************************************************
3157  Fill a notify_info_data with job position.
3158  ********************************************************************/
3159
3160 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3161                                         int snum,
3162                                         struct spoolss_Notify *data,
3163                                         print_queue_struct *queue,
3164                                         struct spoolss_PrinterInfo2 *pinfo2,
3165                                         TALLOC_CTX *mem_ctx)
3166 {
3167         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3168 }
3169
3170 /*******************************************************************
3171  Fill a notify_info_data with submitted time.
3172  ********************************************************************/
3173
3174 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3175                                           int snum,
3176                                           struct spoolss_Notify *data,
3177                                           print_queue_struct *queue,
3178                                           struct spoolss_PrinterInfo2 *pinfo2,
3179                                           TALLOC_CTX *mem_ctx)
3180 {
3181         data->data.string.string = NULL;
3182         data->data.string.size = 0;
3183
3184         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3185                                &data->data.string.string,
3186                                &data->data.string.size);
3187
3188 }
3189
3190 struct s_notify_info_data_table
3191 {
3192         enum spoolss_NotifyType type;
3193         uint16_t field;
3194         const char *name;
3195         enum spoolss_NotifyTable variable_type;
3196         void (*fn) (struct messaging_context *msg_ctx,
3197                     int snum, struct spoolss_Notify *data,
3198                     print_queue_struct *queue,
3199                     struct spoolss_PrinterInfo2 *pinfo2,
3200                     TALLOC_CTX *mem_ctx);
3201 };
3202
3203 /* A table describing the various print notification constants and
3204    whether the notification data is a pointer to a variable sized
3205    buffer, a one value uint32_t or a two value uint32_t. */
3206
3207 static const struct s_notify_info_data_table notify_info_data_table[] =
3208 {
3209 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME,         "PRINTER_NOTIFY_FIELD_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3210 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME,        "PRINTER_NOTIFY_FIELD_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3211 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME,          "PRINTER_NOTIFY_FIELD_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
3212 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME,           "PRINTER_NOTIFY_FIELD_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3213 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME,         "PRINTER_NOTIFY_FIELD_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3214 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT,             "PRINTER_NOTIFY_FIELD_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
3215 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION,            "PRINTER_NOTIFY_FIELD_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
3216 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE,             "PRINTER_NOTIFY_FIELD_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3217 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE,             "PRINTER_NOTIFY_FIELD_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
3218 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR,     "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3219 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS,          "PRINTER_NOTIFY_FIELD_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3220 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE,            "PRINTER_NOTIFY_FIELD_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3221 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
3222 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES,          "PRINTER_NOTIFY_FIELD_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
3223 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY,            "PRINTER_NOTIFY_FIELD_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3224 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
3225 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME,          "PRINTER_NOTIFY_FIELD_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3226 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME,          "PRINTER_NOTIFY_FIELD_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3227 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS,              "PRINTER_NOTIFY_FIELD_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
3228 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING,       "PRINTER_NOTIFY_FIELD_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
3229 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS,               "PRINTER_NOTIFY_FIELD_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
3230 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM,         "PRINTER_NOTIFY_FIELD_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
3231 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES,         "PRINTER_NOTIFY_FIELD_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
3232 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED,       "PRINTER_NOTIFY_FIELD_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3233 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES,         "PRINTER_NOTIFY_FIELD_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
3234 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED,       "PRINTER_NOTIFY_FIELD_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3235 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINTER_NAME,            "JOB_NOTIFY_FIELD_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3236 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_MACHINE_NAME,            "JOB_NOTIFY_FIELD_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3237 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PORT_NAME,               "JOB_NOTIFY_FIELD_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3238 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_USER_NAME,               "JOB_NOTIFY_FIELD_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
3239 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_NOTIFY_NAME,             "JOB_NOTIFY_FIELD_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
3240 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DATATYPE,                "JOB_NOTIFY_FIELD_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3241 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINT_PROCESSOR,         "JOB_NOTIFY_FIELD_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3242 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PARAMETERS,              "JOB_NOTIFY_FIELD_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3243 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DRIVER_NAME,             "JOB_NOTIFY_FIELD_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3244 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DEVMODE,                 "JOB_NOTIFY_FIELD_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3245 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS,                  "JOB_NOTIFY_FIELD_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
3246 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS_STRING,           "JOB_NOTIFY_FIELD_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
3247 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
3248 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DOCUMENT,                "JOB_NOTIFY_FIELD_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
3249 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRIORITY,                "JOB_NOTIFY_FIELD_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3250 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_POSITION,                "JOB_NOTIFY_FIELD_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
3251 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SUBMITTED,               "JOB_NOTIFY_FIELD_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
3252 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_START_TIME,              "JOB_NOTIFY_FIELD_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3253 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_UNTIL_TIME,              "JOB_NOTIFY_FIELD_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3254 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TIME,                    "JOB_NOTIFY_FIELD_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
3255 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_PAGES,             "JOB_NOTIFY_FIELD_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
3256 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PAGES_PRINTED,           "JOB_NOTIFY_FIELD_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
3257 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_BYTES,             "JOB_NOTIFY_FIELD_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
3258 };
3259
3260 /*******************************************************************
3261  Return the variable_type of info_data structure.
3262 ********************************************************************/
3263
3264 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3265                                                                   uint16_t field)
3266 {
3267         int i=0;
3268
3269         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3270                 if ( (notify_info_data_table[i].type == type) &&
3271                      (notify_info_data_table[i].field == field) ) {
3272                         return notify_info_data_table[i].variable_type;
3273                 }
3274         }
3275
3276         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3277
3278         return (enum spoolss_NotifyTable) 0;
3279 }
3280
3281 /****************************************************************************
3282 ****************************************************************************/
3283
3284 static bool search_notify(enum spoolss_NotifyType type,
3285                           uint16_t field,
3286                           int *value)
3287 {
3288         int i;
3289
3290         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3291                 if (notify_info_data_table[i].type == type &&
3292                     notify_info_data_table[i].field == field &&
3293                     notify_info_data_table[i].fn != NULL) {
3294                         *value = i;
3295                         return true;
3296                 }
3297         }
3298
3299         return false;
3300 }
3301
3302 /****************************************************************************
3303 ****************************************************************************/
3304
3305 static void construct_info_data(struct spoolss_Notify *info_data,
3306                                 enum spoolss_NotifyType type,
3307                                 uint16_t field, int id)
3308 {
3309         info_data->type                 = type;
3310         info_data->field.field          = field;
3311         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3312         info_data->job_id               = id;
3313 }
3314
3315 /*******************************************************************
3316  *
3317  * fill a notify_info struct with info asked
3318  *
3319  ********************************************************************/
3320
3321 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3322                                           struct printer_handle *print_hnd,
3323                                           struct spoolss_NotifyInfo *info,
3324                                           struct spoolss_PrinterInfo2 *pinfo2,
3325                                           int snum,
3326                                           const struct spoolss_NotifyOptionType *option_type,
3327                                           uint32_t id,
3328                                           TALLOC_CTX *mem_ctx)
3329 {
3330         int field_num,j;
3331         enum spoolss_NotifyType type;
3332         uint16_t field;
3333
3334         struct spoolss_Notify *current_data;
3335         print_queue_struct *queue=NULL;
3336
3337         type = option_type->type;
3338
3339         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3340                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3341                 option_type->count, lp_servicename(snum)));
3342
3343         for(field_num=0; field_num < option_type->count; field_num++) {
3344                 field = option_type->fields[field_num].field;
3345
3346                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3347
3348                 if (!search_notify(type, field, &j) )
3349                         continue;
3350
3351                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3352                                                       struct spoolss_Notify,
3353                                                       info->count + 1);
3354                 if (info->notifies == NULL) {
3355                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3356                         return false;
3357                 }
3358
3359                 current_data = &info->notifies[info->count];
3360
3361                 construct_info_data(current_data, type, field, id);
3362
3363                 DEBUG(10, ("construct_notify_printer_info: "
3364                            "calling [%s]  snum=%d  printername=[%s])\n",
3365                            notify_info_data_table[j].name, snum,
3366                            pinfo2->printername));
3367
3368                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3369                                              queue, pinfo2, mem_ctx);
3370
3371                 info->count++;
3372         }
3373
3374         return true;
3375 }
3376
3377 /*******************************************************************
3378  *
3379  * fill a notify_info struct with info asked
3380  *
3381  ********************************************************************/
3382
3383 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3384                                        print_queue_struct *queue,
3385                                        struct spoolss_NotifyInfo *info,
3386                                        struct spoolss_PrinterInfo2 *pinfo2,
3387                                        int snum,
3388                                        const struct spoolss_NotifyOptionType *option_type,
3389                                        uint32_t id,
3390                                        TALLOC_CTX *mem_ctx)
3391 {
3392         int field_num,j;
3393         enum spoolss_NotifyType type;
3394         uint16_t field;
3395         struct spoolss_Notify *current_data;
3396
3397         DEBUG(4,("construct_notify_jobs_info\n"));
3398
3399         type = option_type->type;
3400
3401         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3402                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3403                 option_type->count));
3404
3405         for(field_num=0; field_num<option_type->count; field_num++) {
3406                 field = option_type->fields[field_num].field;
3407
3408                 if (!search_notify(type, field, &j) )
3409                         continue;
3410
3411                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3412                                                       struct spoolss_Notify,
3413                                                       info->count + 1);
3414                 if (info->notifies == NULL) {
3415                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3416                         return false;
3417                 }
3418
3419                 current_data=&(info->notifies[info->count]);
3420
3421                 construct_info_data(current_data, type, field, id);
3422                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3423                                              queue, pinfo2, mem_ctx);
3424                 info->count++;
3425         }
3426
3427         return true;
3428 }
3429
3430 /*
3431  * JFM: The enumeration is not that simple, it's even non obvious.
3432  *
3433  * let's take an example: I want to monitor the PRINTER SERVER for
3434  * the printer's name and the number of jobs currently queued.
3435  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3436  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3437  *
3438  * I have 3 printers on the back of my server.
3439  *
3440  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3441  * structures.
3442  *   Number     Data                    Id
3443  *      1       printer 1 name          1
3444  *      2       printer 1 cjob          1
3445  *      3       printer 2 name          2
3446  *      4       printer 2 cjob          2
3447  *      5       printer 3 name          3
3448  *      6       printer 3 name          3
3449  *
3450  * that's the print server case, the printer case is even worse.
3451  */
3452
3453 /*******************************************************************
3454  *
3455  * enumerate all printers on the printserver
3456  * fill a notify_info struct with info asked
3457  *
3458  ********************************************************************/
3459
3460 static WERROR printserver_notify_info(struct pipes_struct *p,
3461                                       struct policy_handle *hnd,
3462                                       struct spoolss_NotifyInfo *info,
3463                                       TALLOC_CTX *mem_ctx)
3464 {
3465         int snum;
3466         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3467         int n_services=lp_numservices();
3468         int i;
3469         struct spoolss_NotifyOption *option;
3470         struct spoolss_NotifyOptionType option_type;
3471         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3472         WERROR result;
3473
3474         DEBUG(4,("printserver_notify_info\n"));
3475
3476         if (!Printer)
3477                 return WERR_BADFID;
3478
3479         option = Printer->notify.option;
3480
3481         info->version   = 2;
3482         info->notifies  = NULL;
3483         info->count     = 0;
3484
3485         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3486            sending a ffpcn() request first */
3487
3488         if ( !option )
3489                 return WERR_BADFID;
3490
3491         for (i=0; i<option->count; i++) {
3492                 option_type = option->types[i];
3493
3494                 if (option_type.type != PRINTER_NOTIFY_TYPE)
3495                         continue;
3496
3497                 for (snum = 0; snum < n_services; snum++) {
3498                         if (!lp_browseable(snum) ||
3499                             !lp_snum_ok(snum) ||
3500                             !lp_print_ok(snum)) {
3501                                 continue; /* skip */
3502                         }
3503
3504                         /* Maybe we should use the SYSTEM server_info here... */
3505                         result = winreg_get_printer(mem_ctx,
3506                                                     get_server_info_system(),
3507                                                     p->msg_ctx,
3508                                                     Printer->servername,
3509                                                     lp_servicename(snum),
3510                                                     &pinfo2);
3511                         if (!W_ERROR_IS_OK(result)) {
3512                                 DEBUG(4, ("printserver_notify_info: "
3513                                           "Failed to get printer [%s]\n",
3514                                           lp_servicename(snum)));
3515                                 continue;
3516                         }
3517
3518
3519                         construct_notify_printer_info(p->msg_ctx,
3520                                                       Printer, info,
3521                                                       pinfo2, snum,
3522                                                       &option_type, snum,
3523                                                       mem_ctx);
3524
3525                         TALLOC_FREE(pinfo2);
3526                 }
3527         }
3528
3529 #if 0
3530         /*
3531          * Debugging information, don't delete.
3532          */
3533
3534         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3535         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3536         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3537
3538         for (i=0; i<info->count; i++) {
3539                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3540                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3541                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3542         }
3543 #endif
3544
3545         return WERR_OK;
3546 }
3547
3548 /*******************************************************************
3549  *
3550  * fill a notify_info struct with info asked
3551  *
3552  ********************************************************************/
3553
3554 static WERROR printer_notify_info(struct pipes_struct *p,
3555                                   struct policy_handle *hnd,
3556                                   struct spoolss_NotifyInfo *info,
3557                                   TALLOC_CTX *mem_ctx)
3558 {
3559         int snum;
3560         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3561         int i;
3562         uint32_t id;
3563         struct spoolss_NotifyOption *option;
3564         struct spoolss_NotifyOptionType option_type;
3565         int count,j;
3566         print_queue_struct *queue=NULL;
3567         print_status_struct status;
3568         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3569         WERROR result;
3570
3571         DEBUG(4,("printer_notify_info\n"));
3572
3573         if (!Printer)
3574                 return WERR_BADFID;
3575
3576         option = Printer->notify.option;
3577         id = 0x0;
3578
3579         info->version   = 2;
3580         info->notifies  = NULL;
3581         info->count     = 0;
3582
3583         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3584            sending a ffpcn() request first */
3585
3586         if ( !option )
3587                 return WERR_BADFID;
3588
3589         get_printer_snum(p, hnd, &snum, NULL);
3590
3591         /* Maybe we should use the SYSTEM server_info here... */
3592         result = winreg_get_printer(mem_ctx,
3593                                     get_server_info_system(),
3594                                     p->msg_ctx,
3595                                     Printer->servername,
3596                                     lp_servicename(snum), &pinfo2);
3597         if (!W_ERROR_IS_OK(result)) {
3598                 return WERR_BADFID;
3599         }
3600
3601         for (i=0; i<option->count; i++) {
3602                 option_type = option->types[i];
3603
3604                 switch (option_type.type) {
3605                 case PRINTER_NOTIFY_TYPE:
3606                         if (construct_notify_printer_info(p->msg_ctx,
3607                                                           Printer, info,
3608                                                           pinfo2, snum,
3609                                                           &option_type, id,
3610                                                           mem_ctx)) {
3611                                 id--;
3612                         }
3613                         break;
3614
3615                 case JOB_NOTIFY_TYPE:
3616
3617                         count = print_queue_status(p->msg_ctx, snum, &queue,
3618                                                    &status);
3619
3620                         for (j=0; j<count; j++) {
3621                                 construct_notify_jobs_info(p->msg_ctx,
3622                                                            &queue[j], info,
3623                                                            pinfo2, snum,
3624                                                            &option_type,
3625                                                            queue[j].job,
3626                                                            mem_ctx);
3627                         }
3628
3629                         SAFE_FREE(queue);
3630                         break;
3631                 }
3632         }
3633
3634         /*
3635          * Debugging information, don't delete.
3636          */
3637         /*
3638         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3639         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3640         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3641
3642         for (i=0; i<info->count; i++) {
3643                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3644                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3645                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3646         }
3647         */
3648
3649         talloc_free(pinfo2);
3650         return WERR_OK;
3651 }
3652
3653 /****************************************************************
3654  _spoolss_RouterRefreshPrinterChangeNotify
3655 ****************************************************************/
3656
3657 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3658                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3659 {
3660         struct spoolss_NotifyInfo *info;
3661
3662         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3663         WERROR result = WERR_BADFID;
3664
3665         /* we always have a spoolss_NotifyInfo struct */
3666         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3667         if (!info) {
3668                 result = WERR_NOMEM;
3669                 goto done;
3670         }
3671
3672         *r->out.info = info;
3673
3674         if (!Printer) {
3675                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3676                         "Invalid handle (%s:%u:%u).\n",
3677                         OUR_HANDLE(r->in.handle)));
3678                 goto done;
3679         }
3680
3681         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3682
3683         /*
3684          *      We are now using the change value, and
3685          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3686          *      I don't have a global notification system, I'm sending back all the
3687          *      informations even when _NOTHING_ has changed.
3688          */
3689
3690         /* We need to keep track of the change value to send back in
3691            RRPCN replies otherwise our updates are ignored. */
3692
3693         Printer->notify.fnpcn = true;
3694
3695         if (Printer->notify.cli_chan != NULL &&
3696             Printer->notify.cli_chan->active_connections > 0) {
3697                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3698                         "Saving change value in request [%x]\n",
3699                         r->in.change_low));
3700                 Printer->notify.change = r->in.change_low;
3701         }
3702
3703         /* just ignore the spoolss_NotifyOption */
3704
3705         switch (Printer->printer_type) {
3706                 case SPLHND_SERVER:
3707                         result = printserver_notify_info(p, r->in.handle,
3708                                                          info, p->mem_ctx);
3709                         break;
3710
3711                 case SPLHND_PRINTER:
3712                         result = printer_notify_info(p, r->in.handle,
3713                                                      info, p->mem_ctx);
3714                         break;
3715         }
3716
3717         Printer->notify.fnpcn = false;
3718
3719 done:
3720         return result;
3721 }
3722
3723 /********************************************************************
3724  * construct_printer_info_0
3725  * fill a printer_info_0 struct
3726  ********************************************************************/
3727
3728 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3729                                       const struct auth_serversupplied_info *server_info,
3730                                       struct messaging_context *msg_ctx,
3731                                       struct spoolss_PrinterInfo2 *info2,
3732                                       struct spoolss_PrinterInfo0 *r,
3733                                       int snum)
3734 {
3735         int count;
3736         struct printer_session_counter *session_counter;
3737         struct timeval setuptime;
3738         print_status_struct status;
3739
3740         r->printername          = talloc_strdup(mem_ctx, info2->printername);
3741         W_ERROR_HAVE_NO_MEMORY(r->printername);
3742
3743         r->servername           = talloc_strdup(mem_ctx, info2->servername);
3744         W_ERROR_HAVE_NO_MEMORY(r->servername);
3745
3746         count = print_queue_length(msg_ctx, snum, &status);
3747
3748         /* check if we already have a counter for this printer */
3749         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3750                 if (session_counter->snum == snum)
3751                         break;
3752         }
3753
3754         /* it's the first time, add it to the list */
3755         if (session_counter == NULL) {
3756                 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3757                 W_ERROR_HAVE_NO_MEMORY(session_counter);
3758                 session_counter->snum           = snum;
3759                 session_counter->counter        = 0;
3760                 DLIST_ADD(counter_list, session_counter);
3761         }
3762
3763         /* increment it */
3764         session_counter->counter++;
3765
3766         r->cjobs                        = count;
3767         r->total_jobs                   = 0;
3768         r->total_bytes                  = 0;
3769
3770         get_startup_time(&setuptime);
3771         init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3772
3773         /* JFM:
3774          * the global_counter should be stored in a TDB as it's common to all the clients
3775          * and should be zeroed on samba startup
3776          */
3777         r->global_counter               = session_counter->counter;
3778         r->total_pages                  = 0;
3779         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3780         SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3781         SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3782         r->free_build                   = SPOOLSS_RELEASE_BUILD;
3783         r->spooling                     = 0;
3784         r->max_spooling                 = 0;
3785         r->session_counter              = session_counter->counter;
3786         r->num_error_out_of_paper       = 0x0;
3787         r->num_error_not_ready          = 0x0;          /* number of print failure */
3788         r->job_error                    = 0x0;
3789         r->number_of_processors         = 0x1;
3790         r->processor_type               = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3791         r->high_part_total_bytes        = 0x0;
3792
3793         /* ChangeID in milliseconds*/
3794         winreg_printer_get_changeid(mem_ctx, server_info, msg_ctx,
3795                                     info2->sharename, &r->change_id);
3796
3797         r->last_error                   = WERR_OK;
3798         r->status                       = nt_printq_status(status.status);
3799         r->enumerate_network_printers   = 0x0;
3800         r->c_setprinter                 = 0x0;
3801         r->processor_architecture       = PROCESSOR_ARCHITECTURE_INTEL;
3802         r->processor_level              = 0x6;          /* 6  ???*/
3803         r->ref_ic                       = 0;
3804         r->reserved2                    = 0;
3805         r->reserved3                    = 0;
3806
3807         return WERR_OK;
3808 }
3809
3810
3811 /********************************************************************
3812  * construct_printer_info1
3813  * fill a spoolss_PrinterInfo1 struct
3814 ********************************************************************/
3815
3816 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3817                                       const struct spoolss_PrinterInfo2 *info2,
3818                                       uint32_t flags,
3819                                       struct spoolss_PrinterInfo1 *r,
3820                                       int snum)
3821 {
3822         r->flags                = flags;
3823
3824         r->description          = talloc_asprintf(mem_ctx, "%s,%s,%s",
3825                                                   info2->printername,
3826                                                   info2->drivername,
3827                                                   info2->location);
3828         W_ERROR_HAVE_NO_MEMORY(r->description);
3829
3830         if (info2->comment == NULL || info2->comment[0] == '\0') {
3831                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
3832         } else {
3833                 r->comment      = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3834         }
3835         W_ERROR_HAVE_NO_MEMORY(r->comment);
3836
3837         r->name                 = talloc_strdup(mem_ctx, info2->printername);
3838         W_ERROR_HAVE_NO_MEMORY(r->name);
3839
3840         return WERR_OK;
3841 }
3842
3843 /********************************************************************
3844  * construct_printer_info2
3845  * fill a spoolss_PrinterInfo2 struct
3846 ********************************************************************/
3847
3848 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3849                                       struct messaging_context *msg_ctx,
3850                                       const struct spoolss_PrinterInfo2 *info2,
3851                                       struct spoolss_PrinterInfo2 *r,
3852                                       int snum)
3853 {
3854         int count;
3855         print_status_struct status;
3856
3857         count = print_queue_length(msg_ctx, snum, &status);
3858
3859         r->servername           = talloc_strdup(mem_ctx, info2->servername);
3860         W_ERROR_HAVE_NO_MEMORY(r->servername);
3861         r->printername          = talloc_strdup(mem_ctx, info2->printername);
3862         W_ERROR_HAVE_NO_MEMORY(r->printername);
3863         r->sharename            = talloc_strdup(mem_ctx, lp_servicename(snum));
3864         W_ERROR_HAVE_NO_MEMORY(r->sharename);
3865         r->portname             = talloc_strdup(mem_ctx, info2->portname);
3866         W_ERROR_HAVE_NO_MEMORY(r->portname);
3867         r->drivername           = talloc_strdup(mem_ctx, info2->drivername);
3868         W_ERROR_HAVE_NO_MEMORY(r->drivername);
3869
3870         if (info2->comment[0] == '\0') {
3871                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
3872         } else {
3873                 r->comment      = talloc_strdup(mem_ctx, info2->comment);
3874         }
3875         W_ERROR_HAVE_NO_MEMORY(r->comment);
3876
3877         r->location             = talloc_strdup(mem_ctx, info2->location);
3878         W_ERROR_HAVE_NO_MEMORY(r->location);
3879         r->sepfile              = talloc_strdup(mem_ctx, info2->sepfile);
3880         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
3881         r->printprocessor       = talloc_strdup(mem_ctx, info2->printprocessor);
3882         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
3883         r->datatype             = talloc_strdup(mem_ctx, info2->datatype);
3884         W_ERROR_HAVE_NO_MEMORY(r->datatype);
3885         r->parameters           = talloc_strdup(mem_ctx, info2->parameters);
3886         W_ERROR_HAVE_NO_MEMORY(r->parameters);
3887
3888         r->attributes           = info2->attributes;
3889
3890         r->priority             = info2->priority;
3891         r->defaultpriority      = info2->defaultpriority;
3892         r->starttime            = info2->starttime;
3893         r->untiltime            = info2->untiltime;
3894         r->status               = nt_printq_status(status.status);
3895         r->cjobs                = count;
3896         r->averageppm           = info2->averageppm;
3897
3898         copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
3899         if (!r->devmode) {
3900                 DEBUG(8,("Returning NULL Devicemode!\n"));
3901         }
3902
3903         r->secdesc = NULL;
3904
3905         if (info2->secdesc != NULL) {
3906                 /* don't use talloc_steal() here unless you do a deep steal of all
3907                    the SEC_DESC members */
3908
3909                 r->secdesc      = dup_sec_desc(mem_ctx, info2->secdesc);
3910         }
3911
3912         return WERR_OK;
3913 }
3914
3915 /********************************************************************
3916  * construct_printer_info3
3917  * fill a spoolss_PrinterInfo3 struct
3918  ********************************************************************/
3919
3920 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
3921                                       const struct spoolss_PrinterInfo2 *info2,
3922                                       struct spoolss_PrinterInfo3 *r,
3923                                       int snum)
3924 {
3925         /* These are the components of the SD we are returning. */
3926
3927         if (info2->secdesc != NULL) {
3928                 /* don't use talloc_steal() here unless you do a deep steal of all
3929                    the SEC_DESC members */
3930
3931                 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
3932                 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
3933         }
3934
3935         return WERR_OK;
3936 }
3937
3938 /********************************************************************
3939  * construct_printer_info4
3940  * fill a spoolss_PrinterInfo4 struct
3941  ********************************************************************/
3942
3943 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
3944                                       const struct spoolss_PrinterInfo2 *info2,
3945                                       struct spoolss_PrinterInfo4 *r,
3946                                       int snum)
3947 {
3948         r->printername  = talloc_strdup(mem_ctx, info2->printername);
3949         W_ERROR_HAVE_NO_MEMORY(r->printername);
3950         r->servername   = talloc_strdup(mem_ctx, info2->servername);
3951         W_ERROR_HAVE_NO_MEMORY(r->servername);
3952
3953         r->attributes   = info2->attributes;
3954
3955         return WERR_OK;
3956 }
3957
3958 /********************************************************************
3959  * construct_printer_info5
3960  * fill a spoolss_PrinterInfo5 struct
3961  ********************************************************************/
3962
3963 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
3964                                       const struct spoolss_PrinterInfo2 *info2,
3965                                       struct spoolss_PrinterInfo5 *r,
3966                                       int snum)
3967 {
3968         r->printername  = talloc_strdup(mem_ctx, info2->printername);
3969         W_ERROR_HAVE_NO_MEMORY(r->printername);
3970         r->portname     = talloc_strdup(mem_ctx, info2->portname);
3971         W_ERROR_HAVE_NO_MEMORY(r->portname);
3972
3973         r->attributes   = info2->attributes;
3974
3975         /* these two are not used by NT+ according to MSDN */
3976         r->device_not_selected_timeout          = 0x0;  /* have seen 0x3a98 */
3977         r->transmission_retry_timeout           = 0x0;  /* have seen 0xafc8 */
3978
3979         return WERR_OK;
3980 }
3981
3982 /********************************************************************
3983  * construct_printer_info_6
3984  * fill a spoolss_PrinterInfo6 struct
3985  ********************************************************************/
3986
3987 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
3988                                       struct messaging_context *msg_ctx,
3989                                       const struct spoolss_PrinterInfo2 *info2,
3990                                       struct spoolss_PrinterInfo6 *r,
3991                                       int snum)
3992 {
3993         int count;
3994         print_status_struct status;
3995
3996         count = print_queue_length(msg_ctx, snum, &status);
3997
3998         r->status = nt_printq_status(status.status);
3999
4000         return WERR_OK;
4001 }
4002
4003 /********************************************************************
4004  * construct_printer_info7
4005  * fill a spoolss_PrinterInfo7 struct
4006  ********************************************************************/
4007
4008 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4009                                       struct messaging_context *msg_ctx,
4010                                       struct printer_handle *print_hnd,
4011                                       struct spoolss_PrinterInfo7 *r,
4012                                       int snum)
4013 {
4014         struct auth_serversupplied_info *server_info;
4015         struct GUID guid;
4016         NTSTATUS status;
4017
4018         status = make_server_info_system(mem_ctx, &server_info);
4019         if (!NT_STATUS_IS_OK(status)) {
4020                 DEBUG(0, ("construct_printer_info7: "
4021                           "Could not create system server_info\n"));
4022                 return WERR_NOMEM;
4023         }
4024
4025         if (is_printer_published(mem_ctx, server_info, msg_ctx,
4026                                  print_hnd->servername,
4027                                  lp_servicename(snum), &guid, NULL)) {
4028                 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4029                 r->action = DSPRINT_PUBLISH;
4030         } else {
4031                 r->guid = talloc_strdup(mem_ctx, "");
4032                 r->action = DSPRINT_UNPUBLISH;
4033         }
4034         W_ERROR_HAVE_NO_MEMORY(r->guid);
4035
4036         TALLOC_FREE(server_info);
4037         return WERR_OK;
4038 }
4039
4040 /********************************************************************
4041  * construct_printer_info8
4042  * fill a spoolss_PrinterInfo8 struct
4043  ********************************************************************/
4044
4045 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4046                                       const struct spoolss_PrinterInfo2 *info2,
4047                                       struct spoolss_DeviceModeInfo *r,
4048                                       int snum)
4049 {
4050         copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4051         if (!r->devmode) {
4052                 DEBUG(8,("Returning NULL Devicemode!\n"));
4053         }
4054
4055         return WERR_OK;
4056 }
4057
4058
4059 /********************************************************************
4060 ********************************************************************/
4061
4062 static bool snum_is_shared_printer(int snum)
4063 {
4064         return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4065 }
4066
4067 /********************************************************************
4068  Spoolss_enumprinters.
4069 ********************************************************************/
4070
4071 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4072                                            const struct auth_serversupplied_info *server_info,
4073                                            struct messaging_context *msg_ctx,
4074                                            uint32_t level,
4075                                            uint32_t flags,
4076                                            union spoolss_PrinterInfo **info_p,
4077                                            uint32_t *count_p)
4078 {
4079         int snum;
4080         int n_services = lp_numservices();
4081         union spoolss_PrinterInfo *info = NULL;
4082         uint32_t count = 0;
4083         WERROR result = WERR_OK;
4084
4085         *count_p = 0;
4086         *info_p = NULL;
4087
4088         for (snum = 0; snum < n_services; snum++) {
4089
4090                 const char *printer;
4091                 struct spoolss_PrinterInfo2 *info2;
4092
4093                 if (!snum_is_shared_printer(snum)) {
4094                         continue;
4095                 }
4096
4097                 printer = lp_const_servicename(snum);
4098
4099                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4100                         printer, snum));
4101
4102                 result = winreg_create_printer(mem_ctx,
4103                                                server_info,
4104                                                msg_ctx,
4105                                                NULL,
4106                                                printer);
4107                 if (!W_ERROR_IS_OK(result)) {
4108                         goto out;
4109                 }
4110
4111                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4112                                             union spoolss_PrinterInfo,
4113                                             count + 1);
4114                 if (!info) {
4115                         result = WERR_NOMEM;
4116                         goto out;
4117                 }
4118
4119                 result = winreg_get_printer(mem_ctx, server_info, msg_ctx,
4120                                             NULL, printer, &info2);
4121                 if (!W_ERROR_IS_OK(result)) {
4122                         goto out;
4123                 }
4124
4125                 switch (level) {
4126                 case 0:
4127                         result = construct_printer_info0(info, server_info,
4128                                                          msg_ctx, info2,
4129                                                          &info[count].info0, snum);
4130                         break;
4131                 case 1:
4132                         result = construct_printer_info1(info, info2, flags,
4133                                                          &info[count].info1, snum);
4134                         break;
4135                 case 2:
4136                         result = construct_printer_info2(info, msg_ctx, info2,
4137                                                          &info[count].info2, snum);
4138                         break;
4139                 case 4:
4140                         result = construct_printer_info4(info, info2,
4141                                                          &info[count].info4, snum);
4142                         break;
4143                 case 5:
4144                         result = construct_printer_info5(info, info2,
4145                                                          &info[count].info5, snum);
4146                         break;
4147
4148                 default:
4149                         result = WERR_UNKNOWN_LEVEL;
4150                         goto out;
4151                 }
4152
4153                 if (!W_ERROR_IS_OK(result)) {
4154                         goto out;
4155                 }
4156
4157                 count++;
4158         }
4159
4160         *count_p = count;
4161         *info_p = info;
4162
4163  out:
4164         if (!W_ERROR_IS_OK(result)) {
4165                 TALLOC_FREE(info);
4166                 return result;
4167         }
4168
4169         *info_p = info;
4170
4171         return WERR_OK;
4172 }
4173
4174 /********************************************************************
4175  * handle enumeration of printers at level 0
4176  ********************************************************************/
4177
4178 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4179                                   const struct auth_serversupplied_info *server_info,
4180                                   struct messaging_context *msg_ctx,
4181                                   uint32_t flags,
4182                                   const char *servername,
4183                                   union spoolss_PrinterInfo **info,
4184                                   uint32_t *count)
4185 {
4186         DEBUG(4,("enum_all_printers_info_0\n"));
4187
4188         return enum_all_printers_info_level(mem_ctx, server_info, msg_ctx,
4189                                             0, flags, info, count);
4190 }
4191
4192
4193 /********************************************************************
4194 ********************************************************************/
4195
4196 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4197                                        const struct auth_serversupplied_info *server_info,
4198                                        struct messaging_context *msg_ctx,
4199                                        uint32_t flags,
4200                                        union spoolss_PrinterInfo **info,
4201                                        uint32_t *count)
4202 {
4203         DEBUG(4,("enum_all_printers_info_1\n"));
4204
4205         return enum_all_printers_info_level(mem_ctx, server_info, msg_ctx,
4206                                             1, flags, info, count);
4207 }
4208
4209 /********************************************************************
4210  enum_all_printers_info_1_local.
4211 *********************************************************************/
4212
4213 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4214                                              const struct auth_serversupplied_info *server_info,
4215                                              struct messaging_context *msg_ctx,
4216                                              union spoolss_PrinterInfo **info,
4217                                              uint32_t *count)
4218 {
4219         DEBUG(4,("enum_all_printers_info_1_local\n"));
4220
4221         return enum_all_printers_info_1(mem_ctx, server_info, msg_ctx,
4222                                         PRINTER_ENUM_ICON8, info, count);
4223 }
4224
4225 /********************************************************************
4226  enum_all_printers_info_1_name.
4227 *********************************************************************/
4228
4229 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4230                                             const struct auth_serversupplied_info *server_info,
4231                                             struct messaging_context *msg_ctx,
4232                                             const char *name,
4233                                             union spoolss_PrinterInfo **info,
4234                                             uint32_t *count)
4235 {
4236         const char *s = name;
4237
4238         DEBUG(4,("enum_all_printers_info_1_name\n"));
4239
4240         if ((name[0] == '\\') && (name[1] == '\\')) {
4241                 s = name + 2;
4242         }
4243
4244         if (!is_myname_or_ipaddr(s)) {
4245                 return WERR_INVALID_NAME;
4246         }
4247
4248         return enum_all_printers_info_1(mem_ctx, server_info, msg_ctx,
4249                                         PRINTER_ENUM_ICON8, info, count);
4250 }
4251
4252 /********************************************************************
4253  enum_all_printers_info_1_network.
4254 *********************************************************************/
4255
4256 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4257                                                const struct auth_serversupplied_info *server_info,
4258                                                struct messaging_context *msg_ctx,
4259                                                const char *name,
4260                                                union spoolss_PrinterInfo **info,
4261                                                uint32_t *count)
4262 {
4263         const char *s = name;
4264
4265         DEBUG(4,("enum_all_printers_info_1_network\n"));
4266
4267         /* If we respond to a enum_printers level 1 on our name with flags
4268            set to PRINTER_ENUM_REMOTE with a list of printers then these
4269            printers incorrectly appear in the APW browse list.
4270            Specifically the printers for the server appear at the workgroup
4271            level where all the other servers in the domain are
4272            listed. Windows responds to this call with a
4273            WERR_CAN_NOT_COMPLETE so we should do the same. */
4274
4275         if (name[0] == '\\' && name[1] == '\\') {
4276                  s = name + 2;
4277         }
4278
4279         if (is_myname_or_ipaddr(s)) {
4280                  return WERR_CAN_NOT_COMPLETE;
4281         }
4282
4283         return enum_all_printers_info_1(mem_ctx, server_info, msg_ctx,
4284                                         PRINTER_ENUM_NAME, info, count);
4285 }
4286
4287 /********************************************************************
4288  * api_spoolss_enumprinters
4289  *
4290  * called from api_spoolss_enumprinters (see this to understand)
4291  ********************************************************************/
4292
4293 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4294                                        const struct auth_serversupplied_info *server_info,
4295                                        struct messaging_context *msg_ctx,
4296                                        union spoolss_PrinterInfo **info,
4297                                        uint32_t *count)
4298 {
4299         DEBUG(4,("enum_all_printers_info_2\n"));
4300
4301         return enum_all_printers_info_level(mem_ctx, server_info, msg_ctx,
4302                                             2, 0, info, count);
4303 }
4304
4305 /********************************************************************
4306  * handle enumeration of printers at level 1
4307  ********************************************************************/
4308
4309 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4310                                   const struct auth_serversupplied_info *server_info,
4311                                   struct messaging_context *msg_ctx,
4312                                   uint32_t flags,
4313                                   const char *name,
4314                                   union spoolss_PrinterInfo **info,
4315                                   uint32_t *count)
4316 {
4317         /* Not all the flags are equals */
4318
4319         if (flags & PRINTER_ENUM_LOCAL) {
4320                 return enum_all_printers_info_1_local(mem_ctx, server_info,
4321                                                       msg_ctx, info, count);
4322         }
4323
4324         if (flags & PRINTER_ENUM_NAME) {
4325                 return enum_all_printers_info_1_name(mem_ctx, server_info,
4326                                                      msg_ctx, name, info,
4327                                                      count);
4328         }
4329
4330         if (flags & PRINTER_ENUM_NETWORK) {
4331                 return enum_all_printers_info_1_network(mem_ctx, server_info,
4332                                                         msg_ctx, name, info,
4333                                                         count);
4334         }
4335
4336         return WERR_OK; /* NT4sp5 does that */
4337 }
4338
4339 /********************************************************************
4340  * handle enumeration of printers at level 2
4341  ********************************************************************/
4342
4343 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4344                                   const struct auth_serversupplied_info *server_info,
4345                                   struct messaging_context *msg_ctx,
4346                                   uint32_t flags,
4347                                   const char *servername,
4348                                   union spoolss_PrinterInfo **info,
4349                                   uint32_t *count)
4350 {
4351         if (flags & PRINTER_ENUM_LOCAL) {
4352                 return enum_all_printers_info_2(mem_ctx, server_info, msg_ctx,
4353                                                 info, count);
4354         }
4355
4356         if (flags & PRINTER_ENUM_NAME) {
4357                 if (!is_myname_or_ipaddr(canon_servername(servername))) {
4358                         return WERR_INVALID_NAME;
4359                 }
4360
4361                 return enum_all_printers_info_2(mem_ctx, server_info, msg_ctx,
4362                                                 info, count);
4363         }
4364
4365         if (flags & PRINTER_ENUM_REMOTE) {
4366                 return WERR_UNKNOWN_LEVEL;
4367         }
4368
4369         return WERR_OK;
4370 }
4371
4372 /********************************************************************
4373  * handle enumeration of printers at level 4
4374  ********************************************************************/
4375
4376 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4377                                   const struct auth_serversupplied_info *server_info,
4378                                   struct messaging_context *msg_ctx,
4379                                   uint32_t flags,
4380                                   const char *servername,
4381                                   union spoolss_PrinterInfo **info,
4382                                   uint32_t *count)
4383 {
4384         DEBUG(4,("enum_all_printers_info_4\n"));
4385
4386         return enum_all_printers_info_level(mem_ctx, server_info, msg_ctx,
4387                                             4, flags, info, count);
4388 }
4389
4390
4391 /********************************************************************
4392  * handle enumeration of printers at level 5
4393  ********************************************************************/
4394
4395 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4396                                   const struct auth_serversupplied_info *server_info,
4397                                   struct messaging_context *msg_ctx,
4398                                   uint32_t flags,
4399                                   const char *servername,
4400                                   union spoolss_PrinterInfo **info,
4401                                   uint32_t *count)
4402 {
4403         DEBUG(4,("enum_all_printers_info_5\n"));
4404
4405         return enum_all_printers_info_level(mem_ctx, server_info, msg_ctx,
4406                                             5, flags, info, count);
4407 }
4408
4409 /****************************************************************
4410  _spoolss_EnumPrinters
4411 ****************************************************************/
4412
4413 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4414                              struct spoolss_EnumPrinters *r)
4415 {
4416         const struct auth_serversupplied_info *server_info = get_server_info_system();
4417         const char *name = NULL;
4418         WERROR result;
4419
4420         /* that's an [in out] buffer */
4421
4422         if (!r->in.buffer && (r->in.offered != 0)) {
4423                 return WERR_INVALID_PARAM;
4424         }
4425
4426         DEBUG(4,("_spoolss_EnumPrinters\n"));
4427
4428         *r->out.needed = 0;
4429         *r->out.count = 0;
4430         *r->out.info = NULL;
4431
4432         /*
4433          * Level 1:
4434          *          flags==PRINTER_ENUM_NAME
4435          *           if name=="" then enumerates all printers
4436          *           if name!="" then enumerate the printer
4437          *          flags==PRINTER_ENUM_REMOTE
4438          *          name is NULL, enumerate printers
4439          * Level 2: name!="" enumerates printers, name can't be NULL
4440          * Level 3: doesn't exist
4441          * Level 4: does a local registry lookup
4442          * Level 5: same as Level 2
4443          */
4444
4445         if (r->in.server) {
4446                 name = talloc_strdup_upper(p->mem_ctx, r->in.server);
4447                 W_ERROR_HAVE_NO_MEMORY(name);
4448         }
4449
4450         switch (r->in.level) {
4451         case 0:
4452                 result = enumprinters_level0(p->mem_ctx, server_info,
4453                                              p->msg_ctx, r->in.flags, name,
4454                                              r->out.info, r->out.count);
4455                 break;
4456         case 1:
4457                 result = enumprinters_level1(p->mem_ctx, server_info,
4458                                              p->msg_ctx, r->in.flags, name,
4459                                              r->out.info, r->out.count);
4460                 break;
4461         case 2:
4462                 result = enumprinters_level2(p->mem_ctx, server_info,
4463                                              p->msg_ctx, r->in.flags, name,
4464                                              r->out.info, r->out.count);
4465                 break;
4466         case 4:
4467                 result = enumprinters_level4(p->mem_ctx, server_info,
4468                                              p->msg_ctx, r->in.flags, name,
4469                                              r->out.info, r->out.count);
4470                 break;
4471         case 5:
4472                 result = enumprinters_level5(p->mem_ctx, server_info,
4473                                              p->msg_ctx, r->in.flags, name,
4474                                              r->out.info, r->out.count);
4475                 break;
4476         default:
4477                 return WERR_UNKNOWN_LEVEL;
4478         }
4479
4480         if (!W_ERROR_IS_OK(result)) {
4481                 return result;
4482         }
4483
4484         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4485                                                      spoolss_EnumPrinters, 
4486                                                      *r->out.info, r->in.level,
4487                                                      *r->out.count);
4488         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4489         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4490
4491         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4492 }
4493
4494 /****************************************************************
4495  _spoolss_GetPrinter
4496 ****************************************************************/
4497
4498 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4499                            struct spoolss_GetPrinter *r)
4500 {
4501         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4502         struct spoolss_PrinterInfo2 *info2 = NULL;
4503         WERROR result = WERR_OK;
4504         const char *servername = NULL;
4505         int snum;
4506
4507         /* that's an [in out] buffer */
4508
4509         if (!r->in.buffer && (r->in.offered != 0)) {
4510                 return WERR_INVALID_PARAM;
4511         }
4512
4513         *r->out.needed = 0;
4514
4515         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4516                 return WERR_BADFID;
4517         }
4518
4519         if (Printer != NULL || Printer->servername != NULL) {
4520                 servername = Printer->servername;
4521         }
4522
4523         result = winreg_get_printer(p->mem_ctx,
4524                                     get_server_info_system(),
4525                                     p->msg_ctx,
4526                                     servername,
4527                                     lp_const_servicename(snum),
4528                                     &info2);
4529         if (!W_ERROR_IS_OK(result)) {
4530                 goto out;
4531         }
4532
4533         switch (r->in.level) {
4534         case 0:
4535                 result = construct_printer_info0(p->mem_ctx,
4536                                                  get_server_info_system(),
4537                                                  p->msg_ctx,
4538                                                  info2,
4539                                                  &r->out.info->info0,
4540                                                  snum);
4541                 break;
4542         case 1:
4543                 result = construct_printer_info1(p->mem_ctx, info2,
4544                                                  PRINTER_ENUM_ICON8,
4545                                                  &r->out.info->info1, snum);
4546                 break;
4547         case 2:
4548                 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4549                                                  &r->out.info->info2, snum);
4550                 break;
4551         case 3:
4552                 result = construct_printer_info3(p->mem_ctx, info2,
4553                                                  &r->out.info->info3, snum);
4554                 break;
4555         case 4:
4556                 result = construct_printer_info4(p->mem_ctx, info2,
4557                                                  &r->out.info->info4, snum);
4558                 break;
4559         case 5:
4560                 result = construct_printer_info5(p->mem_ctx, info2,
4561                                                  &r->out.info->info5, snum);
4562                 break;
4563         case 6:
4564                 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4565                                                  &r->out.info->info6, snum);
4566                 break;
4567         case 7:
4568                 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4569                                                  Printer,
4570                                                  &r->out.info->info7, snum);
4571                 break;
4572         case 8:
4573                 result = construct_printer_info8(p->mem_ctx, info2,
4574                                                  &r->out.info->info8, snum);
4575                 break;
4576         default:
4577                 result = WERR_UNKNOWN_LEVEL;
4578                 break;
4579         }
4580
4581  out:
4582         if (!W_ERROR_IS_OK(result)) {
4583                 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4584                           r->in.level, win_errstr(result)));
4585                 TALLOC_FREE(r->out.info);
4586                 return result;
4587         }
4588
4589         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo, 
4590                                                r->out.info, r->in.level);
4591         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4592
4593         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4594 }
4595
4596 /********************************************************************
4597  ********************************************************************/
4598
4599 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4600         do { \
4601                 if (in && strlen(in)) { \
4602                         out = talloc_strdup(mem_ctx, in); \
4603                 } else { \
4604                         out = talloc_strdup(mem_ctx, ""); \
4605                 } \
4606                 W_ERROR_HAVE_NO_MEMORY(out); \
4607         } while (0);
4608
4609 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4610         do { \
4611                 if (in && strlen(in)) { \
4612                         out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4613                 } else { \
4614                         out = talloc_strdup(mem_ctx, ""); \
4615                 } \
4616                 W_ERROR_HAVE_NO_MEMORY(out); \
4617         } while (0);
4618
4619 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4620                                                   const char **string_array,
4621                                                   const char ***presult,
4622                                                   const char *cservername,
4623                                                   const char *arch,
4624                                                   int version)
4625 {
4626         int i, num_strings = 0;
4627         const char **array = NULL;
4628
4629         if (string_array == NULL) {
4630                 return WERR_INVALID_PARAMETER;;
4631         }
4632
4633         for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4634                 const char *str = NULL;
4635
4636                 if (cservername == NULL || arch == NULL) {
4637                         FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4638                 } else {
4639                         FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4640                 }
4641
4642                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4643                         TALLOC_FREE(array);
4644                         return WERR_NOMEM;
4645                 }
4646         }
4647
4648         if (i > 0) {
4649                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4650                              &array, &num_strings);
4651         }
4652
4653         if (presult) {
4654                 *presult = array;
4655         }
4656
4657         return WERR_OK;
4658 }
4659
4660 /********************************************************************
4661  * fill a spoolss_DriverInfo1 struct
4662  ********************************************************************/
4663
4664 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4665                                         struct spoolss_DriverInfo1 *r,
4666                                         const struct spoolss_DriverInfo8 *driver,
4667                                         const char *servername)
4668 {
4669         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4670         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4671
4672         return WERR_OK;
4673 }
4674
4675 /********************************************************************
4676  * fill a spoolss_DriverInfo2 struct
4677  ********************************************************************/
4678
4679 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4680                                         struct spoolss_DriverInfo2 *r,
4681                                         const struct spoolss_DriverInfo8 *driver,
4682                                         const char *servername)
4683
4684 {
4685         const char *cservername = canon_servername(servername);
4686
4687         r->version              = driver->version;
4688
4689         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4690         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4691         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4692         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4693
4694         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4695                                driver->architecture,
4696                                driver->version,
4697                                driver->driver_path,
4698                                r->driver_path);
4699
4700         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4701                                driver->architecture,
4702                                driver->version,
4703                                driver->data_file,
4704                                r->data_file);
4705
4706         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4707                                driver->architecture,
4708                                driver->version,
4709                                driver->config_file,
4710                                r->config_file);
4711
4712         return WERR_OK;
4713 }
4714
4715 /********************************************************************
4716  * fill a spoolss_DriverInfo3 struct
4717  ********************************************************************/
4718
4719 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4720                                         struct spoolss_DriverInfo3 *r,
4721                                         const struct spoolss_DriverInfo8 *driver,
4722                                         const char *servername)
4723 {
4724         const char *cservername = canon_servername(servername);
4725
4726         r->version              = driver->version;
4727
4728         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4729         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4730         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4731         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4732
4733         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4734                                driver->architecture,
4735                                driver->version,
4736                                driver->driver_path,
4737                                r->driver_path);
4738
4739         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4740                                driver->architecture,
4741                                driver->version,
4742                                driver->data_file,
4743                                r->data_file);
4744
4745         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4746                                driver->architecture,
4747                                driver->version,
4748                                driver->config_file,
4749                                r->config_file);
4750
4751         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4752                                driver->architecture,
4753                                driver->version,
4754                                driver->help_file,
4755                                r->help_file);
4756
4757         FILL_DRIVER_STRING(mem_ctx,
4758                            driver->monitor_name,
4759                            r->monitor_name);
4760
4761         FILL_DRIVER_STRING(mem_ctx,
4762                            driver->default_datatype,
4763                            r->default_datatype);
4764
4765         return string_array_from_driver_info(mem_ctx,
4766                                              driver->dependent_files,
4767                                              &r->dependent_files,
4768                                              cservername,
4769                                              driver->architecture,
4770                                              driver->version);
4771 }
4772
4773 /********************************************************************
4774  * fill a spoolss_DriverInfo4 struct
4775  ********************************************************************/
4776
4777 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4778                                         struct spoolss_DriverInfo4 *r,
4779                                         const struct spoolss_DriverInfo8 *driver,
4780                                         const char *servername)
4781 {
4782         const char *cservername = canon_servername(servername);
4783         WERROR result;
4784
4785         r->version              = driver->version;
4786
4787         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4788         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4789         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4790         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4791
4792         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4793                                driver->architecture,
4794                                driver->version,
4795                                driver->driver_path,
4796                                r->driver_path);
4797
4798         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4799                                driver->architecture,
4800                                driver->version,
4801                                driver->data_file,
4802                                r->data_file);
4803
4804         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4805                                driver->architecture,
4806                                driver->version,
4807                                driver->config_file,
4808                                r->config_file);
4809
4810         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4811                                driver->architecture,
4812                                driver->version,
4813                                driver->help_file,
4814                                r->help_file);
4815
4816         result = string_array_from_driver_info(mem_ctx,
4817                                                driver->dependent_files,
4818                                                &r->dependent_files,
4819                                                cservername,
4820                                                driver->architecture,
4821                                                driver->version);
4822         if (!W_ERROR_IS_OK(result)) {
4823                 return result;
4824         }
4825
4826         FILL_DRIVER_STRING(mem_ctx,
4827                            driver->monitor_name,
4828                            r->monitor_name);
4829
4830         FILL_DRIVER_STRING(mem_ctx,
4831                            driver->default_datatype,
4832                            r->default_datatype);
4833
4834
4835         result = string_array_from_driver_info(mem_ctx,
4836                                                driver->previous_names,
4837                                                &r->previous_names,
4838                                                NULL, NULL, 0);
4839
4840         return result;
4841 }
4842
4843 /********************************************************************
4844  * fill a spoolss_DriverInfo5 struct
4845  ********************************************************************/
4846
4847 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
4848                                         struct spoolss_DriverInfo5 *r,
4849                                         const struct spoolss_DriverInfo8 *driver,
4850                                         const char *servername)
4851 {
4852         const char *cservername = canon_servername(servername);
4853
4854         r->version              = driver->version;
4855
4856         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4857         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4858         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4859         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4860
4861         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4862                                driver->architecture,
4863                                driver->version,
4864                                driver->driver_path,
4865                                r->driver_path);
4866
4867         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4868                                driver->architecture,
4869                                driver->version,
4870                                driver->data_file,
4871                                r->data_file);
4872
4873         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4874                                driver->architecture,
4875                                driver->version,
4876                                driver->config_file,
4877                                r->config_file);
4878
4879         r->driver_attributes    = 0;
4880         r->config_version       = 0;
4881         r->driver_version       = 0;
4882
4883         return WERR_OK;
4884 }
4885 /********************************************************************
4886  * fill a spoolss_DriverInfo6 struct
4887  ********************************************************************/
4888
4889 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
4890                                         struct spoolss_DriverInfo6 *r,
4891                                         const struct spoolss_DriverInfo8 *driver,
4892                                         const char *servername)
4893 {
4894         const char *cservername = canon_servername(servername);
4895         WERROR result;
4896
4897         r->version              = driver->version;
4898
4899         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4900         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4901         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4902         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4903
4904         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4905                                driver->architecture,
4906                                driver->version,
4907                                driver->driver_path,
4908                                r->driver_path);
4909
4910         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4911                                driver->architecture,
4912                                driver->version,
4913                                driver->data_file,
4914                                r->data_file);
4915
4916         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4917                                driver->architecture,
4918                                driver->version,
4919                                driver->config_file,
4920                                r->config_file);
4921
4922         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4923                                driver->architecture,
4924                                driver->version,
4925                                driver->help_file,
4926                                r->help_file);
4927
4928         FILL_DRIVER_STRING(mem_ctx,
4929                            driver->monitor_name,
4930                            r->monitor_name);
4931
4932         FILL_DRIVER_STRING(mem_ctx,
4933                            driver->default_datatype,
4934                            r->default_datatype);
4935
4936         result = string_array_from_driver_info(mem_ctx,
4937                                                driver->dependent_files,
4938                                                &r->dependent_files,
4939                                                cservername,
4940                                                driver->architecture,
4941                                                driver->version);
4942         if (!W_ERROR_IS_OK(result)) {
4943                 return result;
4944         }
4945
4946         result = string_array_from_driver_info(mem_ctx,
4947                                                driver->previous_names,
4948                                                &r->previous_names,
4949                                                NULL, NULL, 0);
4950         if (!W_ERROR_IS_OK(result)) {
4951                 return result;
4952         }
4953
4954         r->driver_date          = driver->driver_date;
4955         r->driver_version       = driver->driver_version;
4956
4957         FILL_DRIVER_STRING(mem_ctx,
4958                            driver->manufacturer_name,
4959                            r->manufacturer_name);
4960         FILL_DRIVER_STRING(mem_ctx,
4961                            driver->manufacturer_url,
4962                            r->manufacturer_url);
4963         FILL_DRIVER_STRING(mem_ctx,
4964                            driver->hardware_id,
4965                            r->hardware_id);
4966         FILL_DRIVER_STRING(mem_ctx,
4967                            driver->provider,
4968                            r->provider);
4969
4970         return WERR_OK;
4971 }
4972
4973 /********************************************************************
4974  * fill a spoolss_DriverInfo8 struct
4975  ********************************************************************/
4976
4977 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
4978                                         struct spoolss_DriverInfo8 *r,
4979                                         const struct spoolss_DriverInfo8 *driver,
4980                                         const char *servername)
4981 {
4982         const char *cservername = canon_servername(servername);
4983         WERROR result;
4984
4985         r->version              = driver->version;
4986
4987         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4988         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4989         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4990         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4991
4992         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4993                                driver->architecture,
4994                                driver->version,
4995                                driver->driver_path,
4996                                r->driver_path);
4997
4998         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4999                                driver->architecture,
5000                                driver->version,
5001                                driver->data_file,
5002                                r->data_file);
5003
5004         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5005                                driver->architecture,
5006                                driver->version,
5007                                driver->config_file,
5008                                r->config_file);
5009
5010         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5011                                driver->architecture,
5012                                driver->version,
5013                                driver->help_file,
5014                                r->help_file);
5015
5016         FILL_DRIVER_STRING(mem_ctx,
5017                            driver->monitor_name,
5018                            r->monitor_name);
5019
5020         FILL_DRIVER_STRING(mem_ctx,
5021                            driver->default_datatype,
5022                            r->default_datatype);
5023
5024         result = string_array_from_driver_info(mem_ctx,
5025                                                driver->dependent_files,
5026                                                &r->dependent_files,
5027                                                cservername,
5028                                                driver->architecture,
5029                                                driver->version);
5030         if (!W_ERROR_IS_OK(result)) {
5031                 return result;
5032         }
5033
5034         result = string_array_from_driver_info(mem_ctx,
5035                                                driver->previous_names,
5036                                                &r->previous_names,
5037                                                NULL, NULL, 0);
5038         if (!W_ERROR_IS_OK(result)) {
5039                 return result;
5040         }
5041
5042         r->driver_date          = driver->driver_date;
5043         r->driver_version       = driver->driver_version;
5044
5045         FILL_DRIVER_STRING(mem_ctx,
5046                            driver->manufacturer_name,
5047                            r->manufacturer_name);
5048         FILL_DRIVER_STRING(mem_ctx,
5049                            driver->manufacturer_url,
5050                            r->manufacturer_url);
5051         FILL_DRIVER_STRING(mem_ctx,
5052                            driver->hardware_id,
5053                            r->hardware_id);
5054         FILL_DRIVER_STRING(mem_ctx,
5055                            driver->provider,
5056                            r->provider);
5057
5058         FILL_DRIVER_STRING(mem_ctx,
5059                            driver->print_processor,
5060                            r->print_processor);
5061         FILL_DRIVER_STRING(mem_ctx,
5062                            driver->vendor_setup,
5063                            r->vendor_setup);
5064
5065         result = string_array_from_driver_info(mem_ctx,
5066                                                driver->color_profiles,
5067                                                &r->color_profiles,
5068                                                NULL, NULL, 0);
5069         if (!W_ERROR_IS_OK(result)) {
5070                 return result;
5071         }
5072
5073         FILL_DRIVER_STRING(mem_ctx,
5074                            driver->inf_path,
5075                            r->inf_path);
5076
5077         r->printer_driver_attributes    = driver->printer_driver_attributes;
5078
5079         result = string_array_from_driver_info(mem_ctx,
5080                                                driver->core_driver_dependencies,
5081                                                &r->core_driver_dependencies,
5082                                                NULL, NULL, 0);
5083         if (!W_ERROR_IS_OK(result)) {
5084                 return result;
5085         }
5086
5087         r->min_inbox_driver_ver_date    = driver->min_inbox_driver_ver_date;
5088         r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5089
5090         return WERR_OK;
5091 }
5092
5093 #if 0 /* disabled until marshalling issues are resolved - gd */
5094 /********************************************************************
5095  ********************************************************************/
5096
5097 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5098                                           struct spoolss_DriverFileInfo *r,
5099                                           const char *cservername,
5100                                           const char *file_name,
5101                                           enum spoolss_DriverFileType file_type,
5102                                           uint32_t file_version)
5103 {
5104         r->file_name    = talloc_asprintf(mem_ctx, "\\\\%s%s",
5105                                           cservername, file_name);
5106         W_ERROR_HAVE_NO_MEMORY(r->file_name);
5107         r->file_type    = file_type;
5108         r->file_version = file_version;
5109
5110         return WERR_OK;
5111 }
5112
5113 /********************************************************************
5114  ********************************************************************/
5115
5116 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5117                                                  const struct spoolss_DriverInfo8 *driver,
5118                                                  const char *cservername,
5119                                                  struct spoolss_DriverFileInfo **info_p,
5120                                                  uint32_t *count_p)
5121 {
5122         struct spoolss_DriverFileInfo *info = NULL;
5123         uint32_t count = 0;
5124         WERROR result;
5125         uint32_t i;
5126
5127         *info_p = NULL;
5128         *count_p = 0;
5129
5130         if (strlen(driver->driver_path)) {
5131                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5132                                             struct spoolss_DriverFileInfo,
5133                                             count + 1);
5134                 W_ERROR_HAVE_NO_MEMORY(info);
5135                 result = fill_spoolss_DriverFileInfo(info,
5136                                                      &info[count],
5137                                                      cservername,
5138                                                      driver->driver_path,
5139                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5140                                                      0);
5141                 W_ERROR_NOT_OK_RETURN(result);
5142                 count++;
5143         }
5144
5145         if (strlen(driver->config_file)) {
5146                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5147                                             struct spoolss_DriverFileInfo,
5148                                             count + 1);
5149                 W_ERROR_HAVE_NO_MEMORY(info);
5150                 result = fill_spoolss_DriverFileInfo(info,
5151                                                      &info[count],
5152                                                      cservername,
5153                                                      driver->config_file,
5154                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5155                                                      0);
5156                 W_ERROR_NOT_OK_RETURN(result);
5157                 count++;
5158         }
5159
5160         if (strlen(driver->data_file)) {
5161                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5162                                             struct spoolss_DriverFileInfo,
5163                                             count + 1);
5164                 W_ERROR_HAVE_NO_MEMORY(info);
5165                 result = fill_spoolss_DriverFileInfo(info,
5166                                                      &info[count],
5167                                                      cservername,
5168                                                      driver->data_file,
5169                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
5170                                                      0);
5171                 W_ERROR_NOT_OK_RETURN(result);
5172                 count++;
5173         }
5174
5175         if (strlen(driver->help_file)) {
5176                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5177                                             struct spoolss_DriverFileInfo,
5178                                             count + 1);
5179                 W_ERROR_HAVE_NO_MEMORY(info);
5180                 result = fill_spoolss_DriverFileInfo(info,
5181                                                      &info[count],
5182                                                      cservername,
5183                                                      driver->help_file,
5184                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
5185                                                      0);
5186                 W_ERROR_NOT_OK_RETURN(result);
5187                 count++;
5188         }
5189
5190         for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5191                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5192                                             struct spoolss_DriverFileInfo,
5193                                             count + 1);
5194                 W_ERROR_HAVE_NO_MEMORY(info);
5195                 result = fill_spoolss_DriverFileInfo(info,
5196                                                      &info[count],
5197                                                      cservername,
5198                                                      driver->dependent_files[i],
5199                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5200                                                      0);
5201                 W_ERROR_NOT_OK_RETURN(result);
5202                 count++;
5203         }
5204
5205         *info_p = info;
5206         *count_p = count;
5207
5208         return WERR_OK;
5209 }
5210
5211 /********************************************************************
5212  * fill a spoolss_DriverInfo101 struct
5213  ********************************************************************/
5214
5215 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5216                                           struct spoolss_DriverInfo101 *r,
5217                                           const struct spoolss_DriverInfo8 *driver,
5218                                           const char *servername)
5219 {
5220         const char *cservername = canon_servername(servername);
5221         WERROR result;
5222
5223         r->version              = driver->version;
5224
5225         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5226         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5227         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5228         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5229
5230         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5231                                                     cservername,
5232                                                     &r->file_info,
5233                                                     &r->file_count);
5234         if (!W_ERROR_IS_OK(result)) {
5235                 return result;
5236         }
5237
5238         FILL_DRIVER_STRING(mem_ctx,
5239                            driver->monitor_name,
5240                            r->monitor_name);
5241
5242         FILL_DRIVER_STRING(mem_ctx,
5243                            driver->default_datatype,
5244                            r->default_datatype);
5245
5246         result = string_array_from_driver_info(mem_ctx,
5247                                                driver->previous_names,
5248                                                &r->previous_names,
5249                                                NULL, NULL, 0);
5250         if (!W_ERROR_IS_OK(result)) {
5251                 return result;
5252         }
5253
5254         r->driver_date          = driver->driver_date;
5255         r->driver_version       = driver->driver_version;
5256
5257         FILL_DRIVER_STRING(mem_ctx,
5258                            driver->manufacturer_name,
5259                            r->manufacturer_name);
5260         FILL_DRIVER_STRING(mem_ctx,
5261                            driver->manufacturer_url,
5262                            r->manufacturer_url);
5263         FILL_DRIVER_STRING(mem_ctx,
5264                            driver->hardware_id,
5265                            r->hardware_id);
5266         FILL_DRIVER_STRING(mem_ctx,
5267                            driver->provider,
5268                            r->provider);
5269
5270         return WERR_OK;
5271 }
5272 #endif
5273 /********************************************************************
5274  ********************************************************************/
5275
5276 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5277                                                   const struct auth_serversupplied_info *server_info,
5278                                                   struct messaging_context *msg_ctx,
5279                                                   uint32_t level,
5280                                                   union spoolss_DriverInfo *r,
5281                                                   int snum,
5282                                                   const char *servername,
5283                                                   const char *architecture,
5284                                                   uint32_t version)
5285 {
5286         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5287         struct spoolss_DriverInfo8 *driver;
5288         WERROR result;
5289
5290         result = winreg_get_printer(mem_ctx,
5291                                     server_info,
5292                                     msg_ctx,
5293                                     servername,
5294                                     lp_const_servicename(snum),
5295                                     &pinfo2);
5296
5297         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5298                 win_errstr(result)));
5299
5300         if (!W_ERROR_IS_OK(result)) {
5301                 return WERR_INVALID_PRINTER_NAME;
5302         }
5303
5304         result = winreg_get_driver(mem_ctx, server_info, msg_ctx,
5305                                    architecture,
5306                                    pinfo2->drivername, version, &driver);
5307
5308         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5309                 win_errstr(result)));
5310
5311         if (!W_ERROR_IS_OK(result)) {
5312                 /*
5313                  * Is this a W2k client ?
5314                  */
5315
5316                 if (version < 3) {
5317                         talloc_free(pinfo2);
5318                         return WERR_UNKNOWN_PRINTER_DRIVER;
5319                 }
5320
5321                 /* Yes - try again with a WinNT driver. */
5322                 version = 2;
5323                 result = winreg_get_driver(mem_ctx, server_info, msg_ctx,
5324                                            architecture,
5325                                            pinfo2->drivername,
5326                                            version, &driver);
5327                 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5328                         win_errstr(result)));
5329                 if (!W_ERROR_IS_OK(result)) {
5330                         talloc_free(pinfo2);
5331                         return WERR_UNKNOWN_PRINTER_DRIVER;
5332                 }
5333         }
5334
5335         switch (level) {
5336         case 1:
5337                 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5338                 break;
5339         case 2:
5340                 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5341                 break;
5342         case 3:
5343                 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5344                 break;
5345         case 4:
5346                 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5347                 break;
5348         case 5:
5349                 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5350                 break;
5351         case 6:
5352                 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5353                 break;
5354         case 8:
5355                 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5356                 break;
5357 #if 0 /* disabled until marshalling issues are resolved - gd */
5358         case 101:
5359                 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5360                 break;
5361 #endif
5362         default:
5363                 result = WERR_UNKNOWN_LEVEL;
5364                 break;
5365         }
5366
5367         talloc_free(pinfo2);
5368         talloc_free(driver);
5369
5370         return result;
5371 }
5372
5373 /****************************************************************
5374  _spoolss_GetPrinterDriver2
5375 ****************************************************************/
5376
5377 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5378                                   struct spoolss_GetPrinterDriver2 *r)
5379 {
5380         struct printer_handle *printer;
5381         WERROR result;
5382
5383         int snum;
5384
5385         /* that's an [in out] buffer */
5386
5387         if (!r->in.buffer && (r->in.offered != 0)) {
5388                 return WERR_INVALID_PARAM;
5389         }
5390
5391         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5392
5393         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5394                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5395                 return WERR_INVALID_PRINTER_NAME;
5396         }
5397
5398         *r->out.needed = 0;
5399         *r->out.server_major_version = 0;
5400         *r->out.server_minor_version = 0;
5401
5402         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5403                 return WERR_BADFID;
5404         }
5405
5406         result = construct_printer_driver_info_level(p->mem_ctx,
5407                                                      get_server_info_system(),
5408                                                      p->msg_ctx,
5409                                                      r->in.level, r->out.info,
5410                                                      snum, printer->servername,
5411                                                      r->in.architecture,
5412                                                      r->in.client_major_version);
5413         if (!W_ERROR_IS_OK(result)) {
5414                 TALLOC_FREE(r->out.info);
5415                 return result;
5416         }
5417
5418         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo, 
5419                                                r->out.info, r->in.level);
5420         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5421
5422         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5423 }
5424
5425
5426 /****************************************************************
5427  _spoolss_StartPagePrinter
5428 ****************************************************************/
5429
5430 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5431                                  struct spoolss_StartPagePrinter *r)
5432 {
5433         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5434
5435         if (!Printer) {
5436                 DEBUG(3,("_spoolss_StartPagePrinter: "
5437                         "Error in startpageprinter printer handle\n"));
5438                 return WERR_BADFID;
5439         }
5440
5441         Printer->page_started = true;
5442         return WERR_OK;
5443 }
5444
5445 /****************************************************************
5446  _spoolss_EndPagePrinter
5447 ****************************************************************/
5448
5449 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5450                                struct spoolss_EndPagePrinter *r)
5451 {
5452         int snum;
5453
5454         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5455
5456         if (!Printer) {
5457                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5458                         OUR_HANDLE(r->in.handle)));
5459                 return WERR_BADFID;
5460         }
5461
5462         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5463                 return WERR_BADFID;
5464
5465         Printer->page_started = false;
5466         print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5467
5468         return WERR_OK;
5469 }
5470
5471 /****************************************************************
5472  _spoolss_StartDocPrinter
5473 ****************************************************************/
5474
5475 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5476                                 struct spoolss_StartDocPrinter *r)
5477 {
5478         struct spoolss_DocumentInfo1 *info_1;
5479         int snum;
5480         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5481         WERROR werr;
5482
5483         if (!Printer) {
5484                 DEBUG(2,("_spoolss_StartDocPrinter: "
5485                         "Invalid handle (%s:%u:%u)\n",
5486                         OUR_HANDLE(r->in.handle)));
5487                 return WERR_BADFID;
5488         }
5489
5490         if (Printer->jobid) {
5491                 DEBUG(2, ("_spoolss_StartDocPrinter: "
5492                           "StartDocPrinter called twice! "
5493                           "(existing jobid = %d)\n", Printer->jobid));
5494                 return WERR_INVALID_HANDLE;
5495         }
5496
5497         if (r->in.level != 1) {
5498                 return WERR_UNKNOWN_LEVEL;
5499         }
5500
5501         info_1 = r->in.info.info1;
5502
5503         /*
5504          * a nice thing with NT is it doesn't listen to what you tell it.
5505          * when asked to send _only_ RAW datas, it tries to send datas
5506          * in EMF format.
5507          *
5508          * So I add checks like in NT Server ...
5509          */
5510
5511         if (info_1->datatype) {
5512                 if (strcmp(info_1->datatype, "RAW") != 0) {
5513                         *r->out.job_id = 0;
5514                         return WERR_INVALID_DATATYPE;
5515                 }
5516         }
5517
5518         /* get the share number of the printer */
5519         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5520                 return WERR_BADFID;
5521         }
5522
5523         werr = print_job_start(get_server_info_system(),
5524                                p->msg_ctx,
5525                                p->client_id->name,
5526                                snum,
5527                                info_1->document_name,
5528                                info_1->output_file,
5529                                Printer->devmode,
5530                                &Printer->jobid);
5531
5532         /* An error occured in print_job_start() so return an appropriate
5533            NT error code. */
5534
5535         if (!W_ERROR_IS_OK(werr)) {
5536                 return werr;
5537         }
5538
5539         Printer->document_started = true;
5540         *r->out.job_id = Printer->jobid;
5541
5542         return WERR_OK;
5543 }
5544
5545 /****************************************************************
5546  _spoolss_EndDocPrinter
5547 ****************************************************************/
5548
5549 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5550                               struct spoolss_EndDocPrinter *r)
5551 {
5552         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5553         NTSTATUS status;
5554         int snum;
5555
5556         if (!Printer) {
5557                 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5558                         OUR_HANDLE(r->in.handle)));
5559                 return WERR_BADFID;
5560         }
5561
5562         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5563                 return WERR_BADFID;
5564         }
5565
5566         Printer->document_started = false;
5567         status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5568         if (!NT_STATUS_IS_OK(status)) {
5569                 DEBUG(2, ("_spoolss_EndDocPrinter: "
5570                           "print_job_end failed [%s]\n",
5571                           nt_errstr(status)));
5572         }
5573
5574         Printer->jobid = 0;
5575         return ntstatus_to_werror(status);
5576 }
5577
5578 /****************************************************************
5579  _spoolss_WritePrinter
5580 ****************************************************************/
5581
5582 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5583                              struct spoolss_WritePrinter *r)
5584 {
5585         ssize_t buffer_written;
5586         int snum;
5587         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5588
5589         if (!Printer) {
5590                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5591                         OUR_HANDLE(r->in.handle)));
5592                 *r->out.num_written = r->in._data_size;
5593                 return WERR_BADFID;
5594         }
5595
5596         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5597                 return WERR_BADFID;
5598
5599         /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5600         buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5601                                                    snum, Printer->jobid,
5602                                                    (const char *)r->in.data.data,
5603                                                    (size_t)r->in._data_size);
5604         if (buffer_written == (ssize_t)-1) {
5605                 *r->out.num_written = 0;
5606                 if (errno == ENOSPC)
5607                         return WERR_NO_SPOOL_SPACE;
5608                 else
5609                         return WERR_ACCESS_DENIED;
5610         }
5611
5612         *r->out.num_written = r->in._data_size;
5613
5614         return WERR_OK;
5615 }
5616
5617 /********************************************************************
5618  * api_spoolss_getprinter
5619  * called from the spoolss dispatcher
5620  *
5621  ********************************************************************/
5622
5623 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5624                               struct pipes_struct *p)
5625 {
5626         const struct auth_serversupplied_info *server_info = get_server_info_system();
5627         int snum;
5628         WERROR errcode = WERR_BADFUNC;
5629         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5630
5631         if (!Printer) {
5632                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5633                         OUR_HANDLE(handle)));
5634                 return WERR_BADFID;
5635         }
5636
5637         if (!get_printer_snum(p, handle, &snum, NULL))
5638                 return WERR_BADFID;
5639
5640         switch (command) {
5641         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5642                 errcode = print_queue_pause(server_info, p->msg_ctx, snum);
5643                 break;
5644         case SPOOLSS_PRINTER_CONTROL_RESUME:
5645         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5646                 errcode = print_queue_resume(server_info, p->msg_ctx, snum);
5647                 break;
5648         case SPOOLSS_PRINTER_CONTROL_PURGE:
5649                 errcode = print_queue_purge(server_info, p->msg_ctx, snum);
5650                 break;
5651         default:
5652                 return WERR_UNKNOWN_LEVEL;
5653         }
5654
5655         return errcode;
5656 }
5657
5658
5659 /****************************************************************
5660  _spoolss_AbortPrinter
5661  * From MSDN: "Deletes printer's spool file if printer is configured
5662  * for spooling"
5663 ****************************************************************/
5664
5665 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
5666                              struct spoolss_AbortPrinter *r)
5667 {
5668         struct printer_handle   *Printer = find_printer_index_by_hnd(p, r->in.handle);
5669         int             snum;
5670         WERROR          errcode = WERR_OK;
5671
5672         if (!Printer) {
5673                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5674                         OUR_HANDLE(r->in.handle)));
5675                 return WERR_BADFID;
5676         }
5677
5678         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5679                 return WERR_BADFID;
5680
5681         if (!Printer->document_started) {
5682                 return WERR_SPL_NO_STARTDOC;
5683         }
5684
5685         errcode = print_job_delete(get_server_info_system(),
5686                                    p->msg_ctx,
5687                                    snum,
5688                                    Printer->jobid);
5689
5690         return errcode;
5691 }
5692
5693 /********************************************************************
5694  * called by spoolss_api_setprinter
5695  * when updating a printer description
5696  ********************************************************************/
5697
5698 static WERROR update_printer_sec(struct policy_handle *handle,
5699                                  struct pipes_struct *p,
5700                                  struct sec_desc_buf *secdesc_ctr)
5701 {
5702         struct spoolss_security_descriptor *new_secdesc = NULL;
5703         struct spoolss_security_descriptor *old_secdesc = NULL;
5704         const char *printer;
5705         WERROR result;
5706         int snum;
5707
5708         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5709
5710         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5711                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5712                          OUR_HANDLE(handle)));
5713
5714                 result = WERR_BADFID;
5715                 goto done;
5716         }
5717
5718         if (secdesc_ctr == NULL) {
5719                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5720                 result = WERR_INVALID_PARAM;
5721                 goto done;
5722         }
5723         printer = lp_const_servicename(snum);
5724
5725         /* Check the user has permissions to change the security
5726            descriptor.  By experimentation with two NT machines, the user
5727            requires Full Access to the printer to change security
5728            information. */
5729
5730         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5731                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5732                 result = WERR_ACCESS_DENIED;
5733                 goto done;
5734         }
5735
5736         /* NT seems to like setting the security descriptor even though
5737            nothing may have actually changed. */
5738         result = winreg_get_printer_secdesc(p->mem_ctx,
5739                                             get_server_info_system(),
5740                                             p->msg_ctx,
5741                                             printer,
5742                                             &old_secdesc);
5743         if (!W_ERROR_IS_OK(result)) {
5744                 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc() failed\n"));
5745                 result = WERR_BADFID;
5746                 goto done;
5747         }
5748
5749         if (DEBUGLEVEL >= 10) {
5750                 struct security_acl *the_acl;
5751                 int i;
5752
5753                 the_acl = old_secdesc->dacl;
5754                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5755                            printer, the_acl->num_aces));
5756
5757                 for (i = 0; i < the_acl->num_aces; i++) {
5758                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5759                                            &the_acl->aces[i].trustee),
5760                                   the_acl->aces[i].access_mask));
5761                 }
5762
5763                 the_acl = secdesc_ctr->sd->dacl;
5764
5765                 if (the_acl) {
5766                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5767                                    printer, the_acl->num_aces));
5768
5769                         for (i = 0; i < the_acl->num_aces; i++) {
5770                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5771                                                    &the_acl->aces[i].trustee),
5772                                            the_acl->aces[i].access_mask));
5773                         }
5774                 } else {
5775                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5776                 }
5777         }
5778
5779         new_secdesc = sec_desc_merge(p->mem_ctx, secdesc_ctr->sd, old_secdesc);
5780         if (new_secdesc == NULL) {
5781                 result = WERR_NOMEM;
5782                 goto done;
5783         }
5784
5785         if (security_descriptor_equal(new_secdesc, old_secdesc)) {
5786                 result = WERR_OK;
5787                 goto done;
5788         }
5789
5790         result = winreg_set_printer_secdesc(p->mem_ctx,
5791                                             get_server_info_system(),
5792                                             p->msg_ctx,
5793                                             printer,
5794                                             new_secdesc);
5795
5796  done:
5797         return result;
5798 }
5799
5800 /********************************************************************
5801  Canonicalize printer info from a client
5802  ********************************************************************/
5803
5804 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
5805                              struct spoolss_SetPrinterInfo2 *info2,
5806                              int snum)
5807 {
5808         fstring printername;
5809         const char *p;
5810
5811         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5812                 "portname=%s drivername=%s comment=%s location=%s\n",
5813                 info2->servername, info2->printername, info2->sharename,
5814                 info2->portname, info2->drivername, info2->comment,
5815                 info2->location));
5816
5817         /* we force some elements to "correct" values */
5818         info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
5819         if (info2->servername == NULL) {
5820                 return false;
5821         }
5822         info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
5823         if (info2->sharename == NULL) {
5824                 return false;
5825         }
5826
5827         /* check to see if we allow printername != sharename */
5828         if (lp_force_printername(snum)) {
5829                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
5830                                         global_myname(), info2->sharename);
5831         } else {
5832                 /* make sure printername is in \\server\printername format */
5833                 fstrcpy(printername, info2->printername);
5834                 p = printername;
5835                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5836                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5837                                 p++;
5838                 }
5839
5840                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
5841                                         global_myname(), p);
5842         }
5843         if (info2->printername == NULL) {
5844                 return false;
5845         }
5846
5847         info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5848         info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5849
5850         return true;
5851 }
5852
5853 /****************************************************************************
5854 ****************************************************************************/
5855
5856 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
5857 {
5858         char *cmd = lp_addport_cmd();
5859         char *command = NULL;
5860         int ret;
5861         bool is_print_op = false;
5862
5863         if ( !*cmd ) {
5864                 return WERR_ACCESS_DENIED;
5865         }
5866
5867         command = talloc_asprintf(ctx,
5868                         "%s \"%s\" \"%s\"", cmd, portname, uri );
5869         if (!command) {
5870                 return WERR_NOMEM;
5871         }
5872
5873         if ( token )
5874                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
5875
5876         DEBUG(10,("Running [%s]\n", command));
5877
5878         /********* BEGIN SePrintOperatorPrivilege **********/
5879
5880         if ( is_print_op )
5881                 become_root();
5882
5883         ret = smbrun(command, NULL);
5884
5885         if ( is_print_op )
5886                 unbecome_root();
5887
5888         /********* END SePrintOperatorPrivilege **********/
5889
5890         DEBUGADD(10,("returned [%d]\n", ret));
5891
5892         TALLOC_FREE(command);
5893
5894         if ( ret != 0 ) {
5895                 return WERR_ACCESS_DENIED;
5896         }
5897
5898         return WERR_OK;
5899 }
5900
5901 /****************************************************************************
5902 ****************************************************************************/
5903
5904 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
5905                              struct spoolss_SetPrinterInfo2 *info2,
5906                              const char *remote_machine,
5907                              struct messaging_context *msg_ctx)
5908 {
5909         char *cmd = lp_addprinter_cmd();
5910         char **qlines;
5911         char *command = NULL;
5912         int numlines;
5913         int ret;
5914         int fd;
5915         bool is_print_op = false;
5916
5917         if (!remote_machine) {
5918                 return false;
5919         }
5920
5921         command = talloc_asprintf(ctx,
5922                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5923                         cmd, info2->printername, info2->sharename,
5924                         info2->portname, info2->drivername,
5925                         info2->location, info2->comment, remote_machine);
5926         if (!command) {
5927                 return false;
5928         }
5929
5930         if ( token )
5931                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
5932
5933         DEBUG(10,("Running [%s]\n", command));
5934
5935         /********* BEGIN SePrintOperatorPrivilege **********/
5936
5937         if ( is_print_op )
5938                 become_root();
5939
5940         if ( (ret = smbrun(command, &fd)) == 0 ) {
5941                 /* Tell everyone we updated smb.conf. */
5942                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
5943         }
5944
5945         if ( is_print_op )
5946                 unbecome_root();
5947
5948         /********* END SePrintOperatorPrivilege **********/
5949
5950         DEBUGADD(10,("returned [%d]\n", ret));
5951
5952         TALLOC_FREE(command);
5953
5954         if ( ret != 0 ) {
5955                 if (fd != -1)
5956                         close(fd);
5957                 return false;
5958         }
5959
5960         /* reload our services immediately */
5961         become_root();
5962         reload_services(msg_ctx, -1, false);
5963         unbecome_root();
5964
5965         numlines = 0;
5966         /* Get lines and convert them back to dos-codepage */
5967         qlines = fd_lines_load(fd, &numlines, 0, NULL);
5968         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5969         close(fd);
5970
5971         /* Set the portname to what the script says the portname should be. */
5972         /* but don't require anything to be return from the script exit a good error code */
5973
5974         if (numlines) {
5975                 /* Set the portname to what the script says the portname should be. */
5976                 info2->portname = talloc_strdup(ctx, qlines[0]);
5977                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5978         }
5979
5980         TALLOC_FREE(qlines);
5981         return true;
5982 }
5983
5984 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
5985                                const struct auth_serversupplied_info *server_info,
5986                                struct messaging_context *msg_ctx,
5987                                int snum,
5988                                struct spoolss_SetPrinterInfo2 *printer,
5989                                struct spoolss_PrinterInfo2 *old_printer)
5990 {
5991         bool force_update = (old_printer == NULL);
5992         const char *dnsdomname;
5993         const char *longname;
5994         const char *uncname;
5995         const char *spooling;
5996         DATA_BLOB buffer;
5997         WERROR result = WERR_OK;
5998
5999         if (force_update || !strequal(printer->drivername, old_printer->drivername)) {
6000                 push_reg_sz(mem_ctx, &buffer, printer->drivername);
6001                 winreg_set_printer_dataex(mem_ctx,
6002                                           server_info,
6003                                           msg_ctx,
6004                                           printer->sharename,
6005                                           SPOOL_DSSPOOLER_KEY,
6006                                           SPOOL_REG_DRIVERNAME,
6007                                           REG_SZ,
6008                                           buffer.data,
6009                                           buffer.length);
6010
6011                 if (!force_update) {
6012                         DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6013                                 printer->drivername));
6014
6015                         notify_printer_driver(server_event_context(), msg_ctx,
6016                                               snum, printer->drivername);
6017                 }
6018         }
6019
6020         if (force_update || !strequal(printer->comment, old_printer->comment)) {
6021                 push_reg_sz(mem_ctx, &buffer, printer->comment);
6022                 winreg_set_printer_dataex(mem_ctx,
6023                                           server_info,
6024                                           msg_ctx,
6025                                           printer->sharename,
6026                                           SPOOL_DSSPOOLER_KEY,
6027                                           SPOOL_REG_DESCRIPTION,
6028                                           REG_SZ,
6029                                           buffer.data,
6030                                           buffer.length);
6031
6032                 if (!force_update) {
6033                         notify_printer_comment(server_event_context(), msg_ctx,
6034                                                snum, printer->comment);
6035                 }
6036         }
6037
6038         if (force_update || !strequal(printer->sharename, old_printer->sharename)) {
6039                 push_reg_sz(mem_ctx, &buffer, printer->sharename);
6040                 winreg_set_printer_dataex(mem_ctx,
6041                                           server_info,
6042                                           msg_ctx,
6043                                           printer->sharename,
6044                                           SPOOL_DSSPOOLER_KEY,
6045                                           SPOOL_REG_PRINTSHARENAME,
6046                                           REG_SZ,
6047                                           buffer.data,
6048                                           buffer.length);
6049
6050                 if (!force_update) {
6051                         notify_printer_sharename(server_event_context(),
6052                                                  msg_ctx,
6053                                                  snum, printer->sharename);
6054                 }
6055         }
6056
6057         if (force_update || !strequal(printer->printername, old_printer->printername)) {
6058                 const char *p;
6059
6060                 p = strrchr(printer->printername, '\\' );
6061                 if (p != NULL) {
6062                         p++;
6063                 } else {
6064                         p = printer->printername;
6065                 }
6066
6067                 push_reg_sz(mem_ctx, &buffer, p);
6068                 winreg_set_printer_dataex(mem_ctx,
6069                                           server_info,
6070                                           msg_ctx,
6071                                           printer->sharename,
6072                                           SPOOL_DSSPOOLER_KEY,
6073                                           SPOOL_REG_PRINTERNAME,
6074                                           REG_SZ,
6075                                           buffer.data,
6076                                           buffer.length);
6077
6078                 if (!force_update) {
6079                         notify_printer_printername(server_event_context(),
6080                                                    msg_ctx, snum, p);
6081                 }
6082         }
6083
6084         if (force_update || !strequal(printer->portname, old_printer->portname)) {
6085                 push_reg_sz(mem_ctx, &buffer, printer->portname);
6086                 winreg_set_printer_dataex(mem_ctx,
6087                                           server_info,
6088                                           msg_ctx,
6089                                           printer->sharename,
6090                                           SPOOL_DSSPOOLER_KEY,
6091                                           SPOOL_REG_PORTNAME,
6092                                           REG_SZ,
6093                                           buffer.data,
6094                                           buffer.length);
6095
6096                 if (!force_update) {
6097                         notify_printer_port(server_event_context(),
6098                                             msg_ctx, snum, printer->portname);
6099                 }
6100         }
6101
6102         if (force_update || !strequal(printer->location, old_printer->location)) {
6103                 push_reg_sz(mem_ctx, &buffer, printer->location);
6104                 winreg_set_printer_dataex(mem_ctx,
6105                                           server_info,
6106                                           msg_ctx,
6107                                           printer->sharename,
6108                                           SPOOL_DSSPOOLER_KEY,
6109                                           SPOOL_REG_LOCATION,
6110                                           REG_SZ,
6111                                           buffer.data,
6112                                           buffer.length);
6113
6114                 if (!force_update) {
6115                         notify_printer_location(server_event_context(),
6116                                                 msg_ctx, snum,
6117                                                 printer->location);
6118                 }
6119         }
6120
6121         if (force_update || !strequal(printer->sepfile, old_printer->sepfile)) {
6122                 push_reg_sz(mem_ctx, &buffer, printer->sepfile);
6123                 winreg_set_printer_dataex(mem_ctx,
6124                                           server_info,
6125                                           msg_ctx,
6126                                           printer->sharename,
6127                                           SPOOL_DSSPOOLER_KEY,
6128                                           SPOOL_REG_PRINTSEPARATORFILE,
6129                                           REG_SZ,
6130                                           buffer.data,
6131                                           buffer.length);
6132
6133                 if (!force_update) {
6134                         notify_printer_location(server_event_context(),
6135                                                 msg_ctx, snum,
6136                                                 printer->location);
6137                 }
6138         }
6139
6140         if (force_update || printer->starttime != old_printer->starttime) {
6141                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6142                 SIVAL(buffer.data, 0, printer->starttime);
6143                 winreg_set_printer_dataex(mem_ctx,
6144                                           server_info,
6145                                           msg_ctx,
6146                                           printer->sharename,
6147                                           SPOOL_DSSPOOLER_KEY,
6148                                           SPOOL_REG_PRINTSTARTTIME,
6149                                           REG_DWORD,
6150                                           buffer.data,
6151                                           buffer.length);
6152         }
6153
6154         if (force_update || printer->untiltime != old_printer->untiltime) {
6155                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6156                 SIVAL(buffer.data, 0, printer->untiltime);
6157                 winreg_set_printer_dataex(mem_ctx,
6158                                           server_info,
6159                                           msg_ctx,
6160                                           printer->sharename,
6161                                           SPOOL_DSSPOOLER_KEY,
6162                                           SPOOL_REG_PRINTENDTIME,
6163                                           REG_DWORD,
6164                                           buffer.data,
6165                                           buffer.length);
6166         }
6167
6168         if (force_update || printer->priority != old_printer->priority) {
6169                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6170                 SIVAL(buffer.data, 0, printer->priority);
6171                 winreg_set_printer_dataex(mem_ctx,
6172                                           server_info,
6173                                           msg_ctx,
6174                                           printer->sharename,
6175                                           SPOOL_DSSPOOLER_KEY,
6176                                           SPOOL_REG_PRIORITY,
6177                                           REG_DWORD,
6178                                           buffer.data,
6179                                           buffer.length);
6180         }
6181
6182         if (force_update || printer->attributes != old_printer->attributes) {
6183                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6184                 SIVAL(buffer.data, 0, (printer->attributes &
6185                                        PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6186                 winreg_set_printer_dataex(mem_ctx,
6187                                           server_info,
6188                                           msg_ctx,
6189                                           printer->sharename,
6190                                           SPOOL_DSSPOOLER_KEY,
6191                                           SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6192                                           REG_DWORD,
6193                                           buffer.data,
6194                                           buffer.length);
6195
6196                 switch (printer->attributes & 0x3) {
6197                         case 0:
6198                                 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6199                                 break;
6200                         case 1:
6201                                 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6202                                 break;
6203                         case 2:
6204                                 spooling = SPOOL_REGVAL_PRINTDIRECT;
6205                                 break;
6206                         default:
6207                                 spooling = "unknown";
6208                 }
6209                 push_reg_sz(mem_ctx, &buffer, spooling);
6210                 winreg_set_printer_dataex(mem_ctx,
6211                                           server_info,
6212                                           msg_ctx,
6213                                           printer->sharename,
6214                                           SPOOL_DSSPOOLER_KEY,
6215                                           SPOOL_REG_PRINTSPOOLING,
6216                                           REG_SZ,
6217                                           buffer.data,
6218                                           buffer.length);
6219         }
6220
6221         push_reg_sz(mem_ctx, &buffer, global_myname());
6222         winreg_set_printer_dataex(mem_ctx,
6223                                   server_info,
6224                                   msg_ctx,
6225                                   printer->sharename,
6226                                   SPOOL_DSSPOOLER_KEY,
6227                                   SPOOL_REG_SHORTSERVERNAME,
6228                                   REG_SZ,
6229                                   buffer.data,
6230                                   buffer.length);
6231
6232         dnsdomname = get_mydnsfullname();
6233         if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6234                 longname = talloc_strdup(mem_ctx, dnsdomname);
6235         } else {
6236                 longname = talloc_strdup(mem_ctx, global_myname());
6237         }
6238         if (longname == NULL) {
6239                 result = WERR_NOMEM;
6240                 goto done;
6241         }
6242
6243         push_reg_sz(mem_ctx, &buffer, longname);
6244         winreg_set_printer_dataex(mem_ctx,
6245                                   server_info,
6246                                   msg_ctx,
6247                                   printer->sharename,
6248                                   SPOOL_DSSPOOLER_KEY,
6249                                   SPOOL_REG_SERVERNAME,
6250                                   REG_SZ,
6251                                   buffer.data,
6252                                   buffer.length);
6253
6254         uncname = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6255                                   global_myname(), printer->sharename);
6256         push_reg_sz(mem_ctx, &buffer, uncname);
6257         winreg_set_printer_dataex(mem_ctx,
6258                                   server_info,
6259                                   msg_ctx,
6260                                   printer->sharename,
6261                                   SPOOL_DSSPOOLER_KEY,
6262                                   SPOOL_REG_UNCNAME,
6263                                   REG_SZ,
6264                                   buffer.data,
6265                                   buffer.length);
6266
6267 done:
6268         return result;
6269 }
6270
6271 /********************************************************************
6272  * Called by spoolss_api_setprinter
6273  * when updating a printer description.
6274  ********************************************************************/
6275
6276 static WERROR update_printer(struct pipes_struct *p,
6277                              struct policy_handle *handle,
6278                              struct spoolss_SetPrinterInfoCtr *info_ctr,
6279                              struct spoolss_DeviceMode *devmode)
6280 {
6281         uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6282         struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6283         struct spoolss_PrinterInfo2 *old_printer;
6284         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6285         const char *servername = NULL;
6286         int snum;
6287         WERROR result = WERR_OK;
6288         TALLOC_CTX *tmp_ctx;
6289
6290         DEBUG(8,("update_printer\n"));
6291
6292         tmp_ctx = talloc_new(p->mem_ctx);
6293         if (tmp_ctx == NULL) {
6294                 return WERR_NOMEM;
6295         }
6296
6297         if (!Printer) {
6298                 result = WERR_BADFID;
6299                 goto done;
6300         }
6301
6302         if (!get_printer_snum(p, handle, &snum, NULL)) {
6303                 result = WERR_BADFID;
6304                 goto done;
6305         }
6306
6307         if (Printer != NULL || Printer->servername != NULL) {
6308                 servername = Printer->servername;
6309         }
6310
6311         result = winreg_get_printer(tmp_ctx,
6312                                     get_server_info_system(),
6313                                     p->msg_ctx,
6314                                     servername,
6315                                     lp_const_servicename(snum),
6316                                     &old_printer);
6317         if (!W_ERROR_IS_OK(result)) {
6318                 result = WERR_BADFID;
6319                 goto done;
6320         }
6321
6322         /* Do sanity check on the requested changes for Samba */
6323         if (!check_printer_ok(tmp_ctx, printer, snum)) {
6324                 result = WERR_INVALID_PARAM;
6325                 goto done;
6326         }
6327
6328         /* FIXME!!! If the driver has changed we really should verify that
6329            it is installed before doing much else   --jerry */
6330
6331         /* Check calling user has permission to update printer description */
6332         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6333                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6334                 result = WERR_ACCESS_DENIED;
6335                 goto done;
6336         }
6337
6338         /* Call addprinter hook */
6339         /* Check changes to see if this is really needed */
6340
6341         if (*lp_addprinter_cmd() &&
6342                         (!strequal(printer->drivername, old_printer->drivername) ||
6343                          !strequal(printer->comment, old_printer->comment) ||
6344                          !strequal(printer->portname, old_printer->portname) ||
6345                          !strequal(printer->location, old_printer->location)) )
6346         {
6347                 /* add_printer_hook() will call reload_services() */
6348                 if (!add_printer_hook(tmp_ctx, p->server_info->ptok,
6349                                       printer, p->client_id->addr,
6350                                       p->msg_ctx)) {
6351                         result = WERR_ACCESS_DENIED;
6352                         goto done;
6353                 }
6354         }
6355
6356         update_dsspooler(tmp_ctx,
6357                          get_server_info_system(),
6358                          p->msg_ctx,
6359                          snum,
6360                          printer,
6361                          old_printer);
6362
6363         printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6364
6365         if (devmode == NULL) {
6366                 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6367         }
6368         result = winreg_update_printer(tmp_ctx,
6369                                        get_server_info_system(),
6370                                        p->msg_ctx,
6371                                        printer->sharename,
6372                                        printer_mask,
6373                                        printer,
6374                                        devmode,
6375                                        NULL);
6376
6377 done:
6378         talloc_free(tmp_ctx);
6379
6380         return result;
6381 }
6382
6383 /****************************************************************************
6384 ****************************************************************************/
6385 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6386                                            struct policy_handle *handle,
6387                                            struct spoolss_SetPrinterInfo7 *info7)
6388 {
6389 #ifdef HAVE_ADS
6390         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6391         WERROR result;
6392         int snum;
6393         struct printer_handle *Printer;
6394
6395         if ( lp_security() != SEC_ADS ) {
6396                 return WERR_UNKNOWN_LEVEL;
6397         }
6398
6399         Printer = find_printer_index_by_hnd(p, handle);
6400
6401         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6402
6403         if (!Printer)
6404                 return WERR_BADFID;
6405
6406         if (!get_printer_snum(p, handle, &snum, NULL))
6407                 return WERR_BADFID;
6408
6409         result = winreg_get_printer(p->mem_ctx,
6410                                     get_server_info_system(),
6411                                     p->msg_ctx,
6412                                     Printer->servername,
6413                                     lp_servicename(snum),
6414                                     &pinfo2);
6415         if (!W_ERROR_IS_OK(result)) {
6416                 return WERR_BADFID;
6417         }
6418
6419         nt_printer_publish(pinfo2,
6420                            get_server_info_system(),
6421                            p->msg_ctx,
6422                            pinfo2,
6423                            info7->action);
6424
6425         TALLOC_FREE(pinfo2);
6426         return WERR_OK;
6427 #else
6428         return WERR_UNKNOWN_LEVEL;
6429 #endif
6430 }
6431
6432 /********************************************************************
6433  ********************************************************************/
6434
6435 static WERROR update_printer_devmode(struct pipes_struct *p,
6436                                      struct policy_handle *handle,
6437                                      struct spoolss_DeviceMode *devmode)
6438 {
6439         int snum;
6440         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6441         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6442
6443         DEBUG(8,("update_printer_devmode\n"));
6444
6445         if (!Printer) {
6446                 return WERR_BADFID;
6447         }
6448
6449         if (!get_printer_snum(p, handle, &snum, NULL)) {
6450                 return WERR_BADFID;
6451         }
6452
6453         /* Check calling user has permission to update printer description */
6454         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6455                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6456                 return WERR_ACCESS_DENIED;
6457         }
6458
6459         return winreg_update_printer(p->mem_ctx,
6460                                      get_server_info_system(),
6461                                      p->msg_ctx,
6462                                      lp_const_servicename(snum),
6463                                      info2_mask,
6464                                      NULL,
6465                                      devmode,
6466                                      NULL);
6467 }
6468
6469
6470 /****************************************************************
6471  _spoolss_SetPrinter
6472 ****************************************************************/
6473
6474 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6475                            struct spoolss_SetPrinter *r)
6476 {
6477         WERROR result;
6478
6479         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6480
6481         if (!Printer) {
6482                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6483                         OUR_HANDLE(r->in.handle)));
6484                 return WERR_BADFID;
6485         }
6486
6487         /* check the level */
6488         switch (r->in.info_ctr->level) {
6489                 case 0:
6490                         return control_printer(r->in.handle, r->in.command, p);
6491                 case 2:
6492                         result = update_printer(p, r->in.handle,
6493                                                 r->in.info_ctr,
6494                                                 r->in.devmode_ctr->devmode);
6495                         if (!W_ERROR_IS_OK(result))
6496                                 return result;
6497                         if (r->in.secdesc_ctr->sd)
6498                                 result = update_printer_sec(r->in.handle, p,
6499                                                             r->in.secdesc_ctr);
6500                         return result;
6501                 case 3:
6502                         return update_printer_sec(r->in.handle, p,
6503                                                   r->in.secdesc_ctr);
6504                 case 7:
6505                         return publish_or_unpublish_printer(p, r->in.handle,
6506                                                             r->in.info_ctr->info.info7);
6507                 case 8:
6508                         return update_printer_devmode(p, r->in.handle,
6509                                                       r->in.devmode_ctr->devmode);
6510                 default:
6511                         return WERR_UNKNOWN_LEVEL;
6512         }
6513 }
6514
6515 /****************************************************************
6516  _spoolss_FindClosePrinterNotify
6517 ****************************************************************/
6518
6519 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
6520                                        struct spoolss_FindClosePrinterNotify *r)
6521 {
6522         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6523
6524         if (!Printer) {
6525                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6526                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6527                 return WERR_BADFID;
6528         }
6529
6530         if (Printer->notify.cli_chan != NULL &&
6531             Printer->notify.cli_chan->active_connections > 0) {
6532                 int snum = -1;
6533
6534                 if (Printer->printer_type == SPLHND_PRINTER) {
6535                         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6536                                 return WERR_BADFID;
6537                         }
6538                 }
6539
6540                 srv_spoolss_replycloseprinter(snum, Printer);
6541         }
6542
6543         Printer->notify.flags=0;
6544         Printer->notify.options=0;
6545         Printer->notify.localmachine[0]='\0';
6546         Printer->notify.printerlocal=0;
6547         TALLOC_FREE(Printer->notify.option);
6548
6549         return WERR_OK;
6550 }
6551
6552 /****************************************************************
6553  _spoolss_AddJob
6554 ****************************************************************/
6555
6556 WERROR _spoolss_AddJob(struct pipes_struct *p,
6557                        struct spoolss_AddJob *r)
6558 {
6559         if (!r->in.buffer && (r->in.offered != 0)) {
6560                 return WERR_INVALID_PARAM;
6561         }
6562
6563         /* this is what a NT server returns for AddJob. AddJob must fail on
6564          * non-local printers */
6565
6566         if (r->in.level != 1) {
6567                 return WERR_UNKNOWN_LEVEL;
6568         }
6569
6570         return WERR_INVALID_PARAM;
6571 }
6572
6573 /****************************************************************************
6574 fill_job_info1
6575 ****************************************************************************/
6576
6577 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6578                              struct spoolss_JobInfo1 *r,
6579                              const print_queue_struct *queue,
6580                              int position, int snum,
6581                              struct spoolss_PrinterInfo2 *pinfo2)
6582 {
6583         struct tm *t;
6584
6585         t = gmtime(&queue->time);
6586
6587         r->job_id               = queue->job;
6588
6589         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6590         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6591         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
6592         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6593         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6594         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6595         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6596         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6597         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6598         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6599         r->text_status          = talloc_strdup(mem_ctx, "");
6600         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6601
6602         r->status               = nt_printj_status(queue->status);
6603         r->priority             = queue->priority;
6604         r->position             = position;
6605         r->total_pages          = queue->page_count;
6606         r->pages_printed        = 0; /* ??? */
6607
6608         init_systemtime(&r->submitted, t);
6609
6610         return WERR_OK;
6611 }
6612
6613 /****************************************************************************
6614 fill_job_info2
6615 ****************************************************************************/
6616
6617 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6618                              struct spoolss_JobInfo2 *r,
6619                              const print_queue_struct *queue,
6620                              int position, int snum,
6621                              struct spoolss_PrinterInfo2 *pinfo2,
6622                              struct spoolss_DeviceMode *devmode)
6623 {
6624         struct tm *t;
6625
6626         t = gmtime(&queue->time);
6627
6628         r->job_id               = queue->job;
6629
6630         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6631         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6632         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
6633         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6634         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6635         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6636         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6637         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6638         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
6639         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6640         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6641         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6642         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
6643         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6644         r->parameters           = talloc_strdup(mem_ctx, "");
6645         W_ERROR_HAVE_NO_MEMORY(r->parameters);
6646         r->driver_name          = talloc_strdup(mem_ctx, pinfo2->drivername);
6647         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6648
6649         r->devmode              = devmode;
6650
6651         r->text_status          = talloc_strdup(mem_ctx, "");
6652         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6653
6654         r->secdesc              = NULL;
6655
6656         r->status               = nt_printj_status(queue->status);
6657         r->priority             = queue->priority;
6658         r->position             = position;
6659         r->start_time           = 0;
6660         r->until_time           = 0;
6661         r->total_pages          = queue->page_count;
6662         r->size                 = queue->size;
6663         init_systemtime(&r->submitted, t);
6664         r->time                 = 0;
6665         r->pages_printed        = 0; /* ??? */
6666
6667         return WERR_OK;
6668 }
6669
6670 /****************************************************************************
6671 fill_job_info3
6672 ****************************************************************************/
6673
6674 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6675                              struct spoolss_JobInfo3 *r,
6676                              const print_queue_struct *queue,
6677                              const print_queue_struct *next_queue,
6678                              int position, int snum,
6679                              struct spoolss_PrinterInfo2 *pinfo2)
6680 {
6681         r->job_id               = queue->job;
6682         r->next_job_id          = 0;
6683         if (next_queue) {
6684                 r->next_job_id  = next_queue->job;
6685         }
6686         r->reserved             = 0;
6687
6688         return WERR_OK;
6689 }
6690
6691 /****************************************************************************
6692  Enumjobs at level 1.
6693 ****************************************************************************/
6694
6695 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6696                               const print_queue_struct *queue,
6697                               uint32_t num_queues, int snum,
6698                               struct spoolss_PrinterInfo2 *pinfo2,
6699                               union spoolss_JobInfo **info_p,
6700                               uint32_t *count)
6701 {
6702         union spoolss_JobInfo *info;
6703         int i;
6704         WERROR result = WERR_OK;
6705
6706         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6707         W_ERROR_HAVE_NO_MEMORY(info);
6708
6709         *count = num_queues;
6710
6711         for (i=0; i<*count; i++) {
6712                 result = fill_job_info1(info,
6713                                         &info[i].info1,
6714                                         &queue[i],
6715                                         i,
6716                                         snum,
6717                                         pinfo2);
6718                 if (!W_ERROR_IS_OK(result)) {
6719                         goto out;
6720                 }
6721         }
6722
6723  out:
6724         if (!W_ERROR_IS_OK(result)) {
6725                 TALLOC_FREE(info);
6726                 *count = 0;
6727                 return result;
6728         }
6729
6730         *info_p = info;
6731
6732         return WERR_OK;
6733 }
6734
6735 /****************************************************************************
6736  Enumjobs at level 2.
6737 ****************************************************************************/
6738
6739 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6740                               const print_queue_struct *queue,
6741                               uint32_t num_queues, int snum,
6742                               struct spoolss_PrinterInfo2 *pinfo2,
6743                               union spoolss_JobInfo **info_p,
6744                               uint32_t *count)
6745 {
6746         union spoolss_JobInfo *info;
6747         int i;
6748         WERROR result = WERR_OK;
6749
6750         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6751         W_ERROR_HAVE_NO_MEMORY(info);
6752
6753         *count = num_queues;
6754
6755         for (i=0; i<*count; i++) {
6756                 struct spoolss_DeviceMode *devmode;
6757
6758                 result = spoolss_create_default_devmode(info,
6759                                                         pinfo2->printername,
6760                                                         &devmode);
6761                 if (!W_ERROR_IS_OK(result)) {
6762                         DEBUG(3, ("Can't proceed w/o a devmode!"));
6763                         goto out;
6764                 }
6765
6766                 result = fill_job_info2(info,
6767                                         &info[i].info2,
6768                                         &queue[i],
6769                                         i,
6770                                         snum,
6771                                         pinfo2,
6772                                         devmode);
6773                 if (!W_ERROR_IS_OK(result)) {
6774                         goto out;
6775                 }
6776         }
6777
6778  out:
6779         if (!W_ERROR_IS_OK(result)) {
6780                 TALLOC_FREE(info);
6781                 *count = 0;
6782                 return result;
6783         }
6784
6785         *info_p = info;
6786
6787         return WERR_OK;
6788 }
6789
6790 /****************************************************************************
6791  Enumjobs at level 3.
6792 ****************************************************************************/
6793
6794 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
6795                               const print_queue_struct *queue,
6796                               uint32_t num_queues, int snum,
6797                               struct spoolss_PrinterInfo2 *pinfo2,
6798                               union spoolss_JobInfo **info_p,
6799                               uint32_t *count)
6800 {
6801         union spoolss_JobInfo *info;
6802         int i;
6803         WERROR result = WERR_OK;
6804
6805         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6806         W_ERROR_HAVE_NO_MEMORY(info);
6807
6808         *count = num_queues;
6809
6810         for (i=0; i<*count; i++) {
6811                 const print_queue_struct *next_queue = NULL;
6812
6813                 if (i+1 < *count) {
6814                         next_queue = &queue[i+1];
6815                 }
6816
6817                 result = fill_job_info3(info,
6818                                         &info[i].info3,
6819                                         &queue[i],
6820                                         next_queue,
6821                                         i,
6822                                         snum,
6823                                         pinfo2);
6824                 if (!W_ERROR_IS_OK(result)) {
6825                         goto out;
6826                 }
6827         }
6828
6829  out:
6830         if (!W_ERROR_IS_OK(result)) {
6831                 TALLOC_FREE(info);
6832                 *count = 0;
6833                 return result;
6834         }
6835
6836         *info_p = info;
6837
6838         return WERR_OK;
6839 }
6840
6841 /****************************************************************
6842  _spoolss_EnumJobs
6843 ****************************************************************/
6844
6845 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
6846                          struct spoolss_EnumJobs *r)
6847 {
6848         WERROR result;
6849         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6850         int snum;
6851         print_status_struct prt_status;
6852         print_queue_struct *queue = NULL;
6853         uint32_t count;
6854
6855         /* that's an [in out] buffer */
6856
6857         if (!r->in.buffer && (r->in.offered != 0)) {
6858                 return WERR_INVALID_PARAM;
6859         }
6860
6861         DEBUG(4,("_spoolss_EnumJobs\n"));
6862
6863         *r->out.needed = 0;
6864         *r->out.count = 0;
6865         *r->out.info = NULL;
6866
6867         /* lookup the printer snum and tdb entry */
6868
6869         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6870                 return WERR_BADFID;
6871         }
6872
6873         result = winreg_get_printer(p->mem_ctx,
6874                                     get_server_info_system(),
6875                                     p->msg_ctx,
6876                                     NULL,
6877                                     lp_const_servicename(snum),
6878                                     &pinfo2);
6879         if (!W_ERROR_IS_OK(result)) {
6880                 return result;
6881         }
6882
6883         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
6884         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
6885                 count, prt_status.status, prt_status.message));
6886
6887         if (count == 0) {
6888                 SAFE_FREE(queue);
6889                 TALLOC_FREE(pinfo2);
6890                 return WERR_OK;
6891         }
6892
6893         switch (r->in.level) {
6894         case 1:
6895                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
6896                                          pinfo2, r->out.info, r->out.count);
6897                 break;
6898         case 2:
6899                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
6900                                          pinfo2, r->out.info, r->out.count);
6901                 break;
6902         case 3:
6903                 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
6904                                          pinfo2, r->out.info, r->out.count);
6905                 break;
6906         default:
6907                 result = WERR_UNKNOWN_LEVEL;
6908                 break;
6909         }
6910
6911         SAFE_FREE(queue);
6912         TALLOC_FREE(pinfo2);
6913
6914         if (!W_ERROR_IS_OK(result)) {
6915                 return result;
6916         }
6917
6918         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6919                                                      spoolss_EnumJobs, 
6920                                                      *r->out.info, r->in.level,
6921                                                      *r->out.count);
6922         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6923         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6924
6925         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6926 }
6927
6928 /****************************************************************
6929  _spoolss_ScheduleJob
6930 ****************************************************************/
6931
6932 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
6933                             struct spoolss_ScheduleJob *r)
6934 {
6935         return WERR_OK;
6936 }
6937
6938 /****************************************************************
6939 ****************************************************************/
6940
6941 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
6942                                struct messaging_context *msg_ctx,
6943                                const char *printer_name,
6944                                uint32_t job_id,
6945                                struct spoolss_SetJobInfo1 *r)
6946 {
6947         char *old_doc_name;
6948
6949         if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
6950                 return WERR_BADFID;
6951         }
6952
6953         if (strequal(old_doc_name, r->document_name)) {
6954                 return WERR_OK;
6955         }
6956
6957         if (!print_job_set_name(server_event_context(), msg_ctx,
6958                                 printer_name, job_id, r->document_name)) {
6959                 return WERR_BADFID;
6960         }
6961
6962         return WERR_OK;
6963 }
6964
6965 /****************************************************************
6966  _spoolss_SetJob
6967 ****************************************************************/
6968
6969 WERROR _spoolss_SetJob(struct pipes_struct *p,
6970                        struct spoolss_SetJob *r)
6971 {
6972         const struct auth_serversupplied_info *server_info = get_server_info_system();
6973         int snum;
6974         WERROR errcode = WERR_BADFUNC;
6975
6976         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6977                 return WERR_BADFID;
6978         }
6979
6980         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
6981                 return WERR_INVALID_PRINTER_NAME;
6982         }
6983
6984         switch (r->in.command) {
6985         case SPOOLSS_JOB_CONTROL_CANCEL:
6986         case SPOOLSS_JOB_CONTROL_DELETE:
6987                 errcode = print_job_delete(server_info, p->msg_ctx,
6988                                            snum, r->in.job_id);
6989                 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
6990                         errcode = WERR_OK;
6991                 }
6992                 break;
6993         case SPOOLSS_JOB_CONTROL_PAUSE:
6994                 if (print_job_pause(server_info, p->msg_ctx,
6995                                     snum, r->in.job_id, &errcode)) {
6996                         errcode = WERR_OK;
6997                 }
6998                 break;
6999         case SPOOLSS_JOB_CONTROL_RESTART:
7000         case SPOOLSS_JOB_CONTROL_RESUME:
7001                 if (print_job_resume(server_info, p->msg_ctx,
7002                                      snum, r->in.job_id, &errcode)) {
7003                         errcode = WERR_OK;
7004                 }
7005                 break;
7006         case 0:
7007                 errcode = WERR_OK;
7008                 break;
7009         default:
7010                 return WERR_UNKNOWN_LEVEL;
7011         }
7012
7013         if (!W_ERROR_IS_OK(errcode)) {
7014                 return errcode;
7015         }
7016
7017         if (r->in.ctr == NULL) {
7018                 return errcode;
7019         }
7020
7021         switch (r->in.ctr->level) {
7022         case 1:
7023                 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7024                                            lp_const_servicename(snum),
7025                                            r->in.job_id,
7026                                            r->in.ctr->info.info1);
7027                 break;
7028         case 2:
7029         case 3:
7030         case 4:
7031         default:
7032                 return WERR_UNKNOWN_LEVEL;
7033         }
7034
7035         return errcode;
7036 }
7037
7038 /****************************************************************************
7039  Enumerates all printer drivers by level and architecture.
7040 ****************************************************************************/
7041
7042 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7043                                                        const struct auth_serversupplied_info *server_info,
7044                                                        struct messaging_context *msg_ctx,
7045                                                        const char *servername,
7046                                                        const char *architecture,
7047                                                        uint32_t level,
7048                                                        union spoolss_DriverInfo **info_p,
7049                                                        uint32_t *count_p)
7050 {
7051         int i;
7052         uint32_t version;
7053         struct spoolss_DriverInfo8 *driver;
7054         union spoolss_DriverInfo *info = NULL;
7055         uint32_t count = 0;
7056         WERROR result = WERR_OK;
7057         uint32_t num_drivers;
7058         const char **drivers;
7059
7060         *count_p = 0;
7061         *info_p = NULL;
7062
7063         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7064                 result = winreg_get_driver_list(mem_ctx, server_info, msg_ctx,
7065                                                 architecture, version,
7066                                                 &num_drivers, &drivers);
7067                 if (!W_ERROR_IS_OK(result)) {
7068                         goto out;
7069                 }
7070                 DEBUG(4, ("we have:[%d] drivers in environment"
7071                           " [%s] and version [%d]\n",
7072                           num_drivers, architecture, version));
7073
7074                 if (num_drivers != 0) {
7075                         info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
7076                                                     union spoolss_DriverInfo,
7077                                                     count + num_drivers);
7078                         if (!info) {
7079                                 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7080                                         "failed to enlarge driver info buffer!\n"));
7081                                 result = WERR_NOMEM;
7082                                 goto out;
7083                         }
7084                 }
7085
7086                 for (i = 0; i < num_drivers; i++) {
7087                         DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7088
7089                         result = winreg_get_driver(mem_ctx, server_info,
7090                                                    msg_ctx,
7091                                                    architecture, drivers[i],
7092                                                    version, &driver);
7093                         if (!W_ERROR_IS_OK(result)) {
7094                                 goto out;
7095                         }
7096
7097                         switch (level) {
7098                         case 1:
7099                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
7100                                                                    driver, servername);
7101                                 break;
7102                         case 2:
7103                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
7104                                                                    driver, servername);
7105                                 break;
7106                         case 3:
7107                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
7108                                                                    driver, servername);
7109                                 break;
7110                         case 4:
7111                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
7112                                                                    driver, servername);
7113                                 break;
7114                         case 5:
7115                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
7116                                                                    driver, servername);
7117                                 break;
7118                         case 6:
7119                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
7120                                                                    driver, servername);
7121                                 break;
7122                         case 8:
7123                                 result = fill_printer_driver_info8(info, &info[count+i].info8,
7124                                                                    driver, servername);
7125                                 break;
7126                         default:
7127                                 result = WERR_UNKNOWN_LEVEL;
7128                                 break;
7129                         }
7130
7131                         TALLOC_FREE(driver);
7132
7133                         if (!W_ERROR_IS_OK(result)) {
7134                                 goto out;
7135                         }
7136                 }
7137
7138                 count += num_drivers;
7139                 TALLOC_FREE(drivers);
7140         }
7141
7142  out:
7143         TALLOC_FREE(drivers);
7144
7145         if (!W_ERROR_IS_OK(result)) {
7146                 TALLOC_FREE(info);
7147                 return result;
7148         }
7149
7150         *info_p = info;
7151         *count_p = count;
7152
7153         return WERR_OK;
7154 }
7155
7156 /****************************************************************************
7157  Enumerates all printer drivers by level.
7158 ****************************************************************************/
7159
7160 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7161                                        const struct auth_serversupplied_info *server_info,
7162                                        struct messaging_context *msg_ctx,
7163                                        const char *servername,
7164                                        const char *architecture,
7165                                        uint32_t level,
7166                                        union spoolss_DriverInfo **info_p,
7167                                        uint32_t *count_p)
7168 {
7169         uint32_t a,i;
7170         WERROR result = WERR_OK;
7171
7172         if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7173
7174                 for (a=0; archi_table[a].long_archi != NULL; a++) {
7175
7176                         union spoolss_DriverInfo *info = NULL;
7177                         uint32_t count = 0;
7178
7179                         result = enumprinterdrivers_level_by_architecture(mem_ctx,
7180                                                                           server_info,
7181                                                                           msg_ctx,
7182                                                                           servername,
7183                                                                           archi_table[a].long_archi,
7184                                                                           level,
7185                                                                           &info,
7186                                                                           &count);
7187                         if (!W_ERROR_IS_OK(result)) {
7188                                 continue;
7189                         }
7190
7191                         for (i=0; i < count; i++) {
7192                                 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7193                                              info[i], info_p, count_p);
7194                         }
7195                 }
7196
7197                 return result;
7198         }
7199
7200         return enumprinterdrivers_level_by_architecture(mem_ctx,
7201                                                         server_info,
7202                                                         msg_ctx,
7203                                                         servername,
7204                                                         architecture,
7205                                                         level,
7206                                                         info_p,
7207                                                         count_p);
7208 }
7209
7210 /****************************************************************
7211  _spoolss_EnumPrinterDrivers
7212 ****************************************************************/
7213
7214 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7215                                    struct spoolss_EnumPrinterDrivers *r)
7216 {
7217         const char *cservername;
7218         WERROR result;
7219
7220         /* that's an [in out] buffer */
7221
7222         if (!r->in.buffer && (r->in.offered != 0)) {
7223                 return WERR_INVALID_PARAM;
7224         }
7225
7226         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7227
7228         *r->out.needed = 0;
7229         *r->out.count = 0;
7230         *r->out.info = NULL;
7231
7232         cservername = canon_servername(r->in.server);
7233
7234         if (!is_myname_or_ipaddr(cservername)) {
7235                 return WERR_UNKNOWN_PRINTER_DRIVER;
7236         }
7237
7238         result = enumprinterdrivers_level(p->mem_ctx,
7239                                           get_server_info_system(),
7240                                           p->msg_ctx,
7241                                           cservername,
7242                                           r->in.environment,
7243                                           r->in.level,
7244                                           r->out.info,
7245                                           r->out.count);
7246         if (!W_ERROR_IS_OK(result)) {
7247                 return result;
7248         }
7249
7250         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7251                                                      spoolss_EnumPrinterDrivers, 
7252                                                      *r->out.info, r->in.level,
7253                                                      *r->out.count);
7254         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7255         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7256
7257         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7258 }
7259
7260 /****************************************************************
7261  _spoolss_EnumForms
7262 ****************************************************************/
7263
7264 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7265                           struct spoolss_EnumForms *r)
7266 {
7267         WERROR result;
7268
7269         *r->out.count = 0;
7270         *r->out.needed = 0;
7271         *r->out.info = NULL;
7272
7273         /* that's an [in out] buffer */
7274
7275         if (!r->in.buffer && (r->in.offered != 0) ) {
7276                 return WERR_INVALID_PARAM;
7277         }
7278
7279         DEBUG(4,("_spoolss_EnumForms\n"));
7280         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7281         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7282
7283         switch (r->in.level) {
7284         case 1:
7285                 result = winreg_printer_enumforms1(p->mem_ctx,
7286                                                    get_server_info_system(),
7287                                                    p->msg_ctx,
7288                                                    r->out.count,
7289                                                    r->out.info);
7290                 break;
7291         default:
7292                 result = WERR_UNKNOWN_LEVEL;
7293                 break;
7294         }
7295
7296         if (!W_ERROR_IS_OK(result)) {
7297                 return result;
7298         }
7299
7300         if (*r->out.count == 0) {
7301                 return WERR_NO_MORE_ITEMS;
7302         }
7303
7304         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7305                                                      spoolss_EnumForms, 
7306                                                      *r->out.info, r->in.level,
7307                                                      *r->out.count);
7308         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7309         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7310
7311         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7312 }
7313
7314 /****************************************************************
7315  _spoolss_GetForm
7316 ****************************************************************/
7317
7318 WERROR _spoolss_GetForm(struct pipes_struct *p,
7319                         struct spoolss_GetForm *r)
7320 {
7321         WERROR result;
7322
7323         /* that's an [in out] buffer */
7324
7325         if (!r->in.buffer && (r->in.offered != 0)) {
7326                 return WERR_INVALID_PARAM;
7327         }
7328
7329         DEBUG(4,("_spoolss_GetForm\n"));
7330         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7331         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7332
7333         switch (r->in.level) {
7334         case 1:
7335                 result = winreg_printer_getform1(p->mem_ctx,
7336                                                  get_server_info_system(),
7337                                                  p->msg_ctx,
7338                                                  r->in.form_name,
7339                                                  &r->out.info->info1);
7340                 break;
7341         default:
7342                 result = WERR_UNKNOWN_LEVEL;
7343                 break;
7344         }
7345
7346         if (!W_ERROR_IS_OK(result)) {
7347                 TALLOC_FREE(r->out.info);
7348                 return result;
7349         }
7350
7351         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo, 
7352                                                r->out.info, r->in.level);
7353         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7354
7355         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7356 }
7357
7358 /****************************************************************************
7359 ****************************************************************************/
7360
7361 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7362                           struct spoolss_PortInfo1 *r,
7363                           const char *name)
7364 {
7365         r->port_name = talloc_strdup(mem_ctx, name);
7366         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7367
7368         return WERR_OK;
7369 }
7370
7371 /****************************************************************************
7372  TODO: This probably needs distinguish between TCP/IP and Local ports
7373  somehow.
7374 ****************************************************************************/
7375
7376 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7377                           struct spoolss_PortInfo2 *r,
7378                           const char *name)
7379 {
7380         r->port_name = talloc_strdup(mem_ctx, name);
7381         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7382
7383         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7384         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7385
7386         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7387         W_ERROR_HAVE_NO_MEMORY(r->description);
7388
7389         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7390         r->reserved = 0;
7391
7392         return WERR_OK;
7393 }
7394
7395
7396 /****************************************************************************
7397  wrapper around the enumer ports command
7398 ****************************************************************************/
7399
7400 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7401 {
7402         char *cmd = lp_enumports_cmd();
7403         char **qlines = NULL;
7404         char *command = NULL;
7405         int numlines;
7406         int ret;
7407         int fd;
7408
7409         *count = 0;
7410         *lines = NULL;
7411
7412         /* if no hook then just fill in the default port */
7413
7414         if ( !*cmd ) {
7415                 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7416                         return WERR_NOMEM;
7417                 }
7418                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7419                         TALLOC_FREE(qlines);
7420                         return WERR_NOMEM;
7421                 }
7422                 qlines[1] = NULL;
7423                 numlines = 1;
7424         }
7425         else {
7426                 /* we have a valid enumport command */
7427
7428                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7429                 if (!command) {
7430                         return WERR_NOMEM;
7431                 }
7432
7433                 DEBUG(10,("Running [%s]\n", command));
7434                 ret = smbrun(command, &fd);
7435                 DEBUG(10,("Returned [%d]\n", ret));
7436                 TALLOC_FREE(command);
7437                 if (ret != 0) {
7438                         if (fd != -1) {
7439                                 close(fd);
7440                         }
7441                         return WERR_ACCESS_DENIED;
7442                 }
7443
7444                 numlines = 0;
7445                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7446                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7447                 close(fd);
7448         }
7449
7450         *count = numlines;
7451         *lines = qlines;
7452
7453         return WERR_OK;
7454 }
7455
7456 /****************************************************************************
7457  enumports level 1.
7458 ****************************************************************************/
7459
7460 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7461                                 union spoolss_PortInfo **info_p,
7462                                 uint32_t *count)
7463 {
7464         union spoolss_PortInfo *info = NULL;
7465         int i=0;
7466         WERROR result = WERR_OK;
7467         char **qlines = NULL;
7468         int numlines = 0;
7469
7470         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7471         if (!W_ERROR_IS_OK(result)) {
7472                 goto out;
7473         }
7474
7475         if (numlines) {
7476                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7477                 if (!info) {
7478                         DEBUG(10,("Returning WERR_NOMEM\n"));
7479                         result = WERR_NOMEM;
7480                         goto out;
7481                 }
7482
7483                 for (i=0; i<numlines; i++) {
7484                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7485                         result = fill_port_1(info, &info[i].info1, qlines[i]);
7486                         if (!W_ERROR_IS_OK(result)) {
7487                                 goto out;
7488                         }
7489                 }
7490         }
7491         TALLOC_FREE(qlines);
7492
7493 out:
7494         if (!W_ERROR_IS_OK(result)) {
7495                 TALLOC_FREE(info);
7496                 TALLOC_FREE(qlines);
7497                 *count = 0;
7498                 *info_p = NULL;
7499                 return result;
7500         }
7501
7502         *info_p = info;
7503         *count = numlines;
7504
7505         return WERR_OK;
7506 }
7507
7508 /****************************************************************************
7509  enumports level 2.
7510 ****************************************************************************/
7511
7512 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7513                                 union spoolss_PortInfo **info_p,
7514                                 uint32_t *count)
7515 {
7516         union spoolss_PortInfo *info = NULL;
7517         int i=0;
7518         WERROR result = WERR_OK;
7519         char **qlines = NULL;
7520         int numlines = 0;
7521
7522         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7523         if (!W_ERROR_IS_OK(result)) {
7524                 goto out;
7525         }
7526
7527         if (numlines) {
7528                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7529                 if (!info) {
7530                         DEBUG(10,("Returning WERR_NOMEM\n"));
7531                         result = WERR_NOMEM;
7532                         goto out;
7533                 }
7534
7535                 for (i=0; i<numlines; i++) {
7536                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7537                         result = fill_port_2(info, &info[i].info2, qlines[i]);
7538                         if (!W_ERROR_IS_OK(result)) {
7539                                 goto out;
7540                         }
7541                 }
7542         }
7543         TALLOC_FREE(qlines);
7544
7545 out:
7546         if (!W_ERROR_IS_OK(result)) {
7547                 TALLOC_FREE(info);
7548                 TALLOC_FREE(qlines);
7549                 *count = 0;
7550                 *info_p = NULL;
7551                 return result;
7552         }
7553
7554         *info_p = info;
7555         *count = numlines;
7556
7557         return WERR_OK;
7558 }
7559
7560 /****************************************************************
7561  _spoolss_EnumPorts
7562 ****************************************************************/
7563
7564 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
7565                           struct spoolss_EnumPorts *r)
7566 {
7567         WERROR result;
7568
7569         /* that's an [in out] buffer */
7570
7571         if (!r->in.buffer && (r->in.offered != 0)) {
7572                 return WERR_INVALID_PARAM;
7573         }
7574
7575         DEBUG(4,("_spoolss_EnumPorts\n"));
7576
7577         *r->out.count = 0;
7578         *r->out.needed = 0;
7579         *r->out.info = NULL;
7580
7581         switch (r->in.level) {
7582         case 1:
7583                 result = enumports_level_1(p->mem_ctx, r->out.info,
7584                                            r->out.count);
7585                 break;
7586         case 2:
7587                 result = enumports_level_2(p->mem_ctx, r->out.info,
7588                                            r->out.count);
7589                 break;
7590         default:
7591                 return WERR_UNKNOWN_LEVEL;
7592         }
7593
7594         if (!W_ERROR_IS_OK(result)) {
7595                 return result;
7596         }
7597
7598         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7599                                                      spoolss_EnumPorts, 
7600                                                      *r->out.info, r->in.level,
7601                                                      *r->out.count);
7602         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7603         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7604
7605         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7606 }
7607
7608 /****************************************************************************
7609 ****************************************************************************/
7610
7611 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
7612                                            const char *server,
7613                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
7614                                            struct spoolss_DeviceMode *devmode,
7615                                            struct security_descriptor *secdesc,
7616                                            struct spoolss_UserLevelCtr *user_ctr,
7617                                            struct policy_handle *handle)
7618 {
7619         struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
7620         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
7621         int     snum;
7622         WERROR err = WERR_OK;
7623
7624         /* samba does not have a concept of local, non-shared printers yet, so
7625          * make sure we always setup sharename - gd */
7626         if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
7627             (info2->printername != NULL && info2->printername[0] != '\0')) {
7628                 DEBUG(5, ("spoolss_addprinterex_level_2: "
7629                         "no sharename has been set, setting printername %s as sharename\n",
7630                         info2->printername));
7631                 info2->sharename = info2->printername;
7632         }
7633
7634         /* check to see if the printer already exists */
7635         if ((snum = print_queue_snum(info2->sharename)) != -1) {
7636                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7637                         info2->sharename));
7638                 return WERR_PRINTER_ALREADY_EXISTS;
7639         }
7640
7641         if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7642                 if ((snum = print_queue_snum(info2->printername)) != -1) {
7643                         DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7644                                 info2->printername));
7645                         return WERR_PRINTER_ALREADY_EXISTS;
7646                 }
7647         }
7648
7649         /* validate printer info struct */
7650         if (!info2->printername || strlen(info2->printername) == 0) {
7651                 return WERR_INVALID_PRINTER_NAME;
7652         }
7653         if (!info2->portname || strlen(info2->portname) == 0) {
7654                 return WERR_UNKNOWN_PORT;
7655         }
7656         if (!info2->drivername || strlen(info2->drivername) == 0) {
7657                 return WERR_UNKNOWN_PRINTER_DRIVER;
7658         }
7659         if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
7660                 return WERR_UNKNOWN_PRINTPROCESSOR;
7661         }
7662
7663         /* FIXME!!!  smbd should check to see if the driver is installed before
7664            trying to add a printer like this  --jerry */
7665
7666         if (*lp_addprinter_cmd() ) {
7667                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7668                                        info2, p->client_id->addr,
7669                                        p->msg_ctx) ) {
7670                         return WERR_ACCESS_DENIED;
7671                 }
7672         } else {
7673                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7674                         "smb.conf parameter \"addprinter command\" is defined. This"
7675                         "parameter must exist for this call to succeed\n",
7676                         info2->sharename ));
7677         }
7678
7679         if ((snum = print_queue_snum(info2->sharename)) == -1) {
7680                 return WERR_ACCESS_DENIED;
7681         }
7682
7683         /* you must be a printer admin to add a new printer */
7684         if (!print_access_check(get_server_info_system(),
7685                                 p->msg_ctx,
7686                                 snum,
7687                                 PRINTER_ACCESS_ADMINISTER)) {
7688                 return WERR_ACCESS_DENIED;
7689         }
7690
7691         /*
7692          * Do sanity check on the requested changes for Samba.
7693          */
7694
7695         if (!check_printer_ok(p->mem_ctx, info2, snum)) {
7696                 return WERR_INVALID_PARAM;
7697         }
7698
7699         if (devmode == NULL) {
7700                 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
7701         }
7702
7703         update_dsspooler(p->mem_ctx,
7704                          get_server_info_system(),
7705                          p->msg_ctx,
7706                          0,
7707                          info2,
7708                          NULL);
7709
7710         err = winreg_update_printer(p->mem_ctx,
7711                                     get_server_info_system(),
7712                                     p->msg_ctx,
7713                                     info2->sharename,
7714                                     info2_mask,
7715                                     info2,
7716                                     devmode,
7717                                     secdesc);
7718         if (!W_ERROR_IS_OK(err)) {
7719                 return err;
7720         }
7721
7722         if (!open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER)) {
7723                 /* Handle open failed - remove addition. */
7724                 ZERO_STRUCTP(handle);
7725                 return WERR_ACCESS_DENIED;
7726         }
7727
7728         return WERR_OK;
7729 }
7730
7731 /****************************************************************
7732  _spoolss_AddPrinterEx
7733 ****************************************************************/
7734
7735 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
7736                              struct spoolss_AddPrinterEx *r)
7737 {
7738         switch (r->in.info_ctr->level) {
7739         case 1:
7740                 /* we don't handle yet */
7741                 /* but I know what to do ... */
7742                 return WERR_UNKNOWN_LEVEL;
7743         case 2:
7744                 return spoolss_addprinterex_level_2(p, r->in.server,
7745                                                     r->in.info_ctr,
7746                                                     r->in.devmode_ctr->devmode,
7747                                                     r->in.secdesc_ctr->sd,
7748                                                     r->in.userlevel_ctr,
7749                                                     r->out.handle);
7750         default:
7751                 return WERR_UNKNOWN_LEVEL;
7752         }
7753 }
7754
7755 /****************************************************************
7756  _spoolss_AddPrinter
7757 ****************************************************************/
7758
7759 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
7760                            struct spoolss_AddPrinter *r)
7761 {
7762         struct spoolss_AddPrinterEx a;
7763         struct spoolss_UserLevelCtr userlevel_ctr;
7764
7765         ZERO_STRUCT(userlevel_ctr);
7766
7767         userlevel_ctr.level = 1;
7768
7769         a.in.server             = r->in.server;
7770         a.in.info_ctr           = r->in.info_ctr;
7771         a.in.devmode_ctr        = r->in.devmode_ctr;
7772         a.in.secdesc_ctr        = r->in.secdesc_ctr;
7773         a.in.userlevel_ctr      = &userlevel_ctr;
7774         a.out.handle            = r->out.handle;
7775
7776         return _spoolss_AddPrinterEx(p, &a);
7777 }
7778
7779 /****************************************************************
7780  _spoolss_AddPrinterDriverEx
7781 ****************************************************************/
7782
7783 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
7784                                    struct spoolss_AddPrinterDriverEx *r)
7785 {
7786         WERROR err = WERR_OK;
7787         const char *driver_name = NULL;
7788         uint32_t version;
7789         const char *fn;
7790
7791         switch (p->opnum) {
7792                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7793                         fn = "_spoolss_AddPrinterDriver";
7794                         break;
7795                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7796                         fn = "_spoolss_AddPrinterDriverEx";
7797                         break;
7798                 default:
7799                         return WERR_INVALID_PARAM;
7800         }
7801
7802         /*
7803          * we only support the semantics of AddPrinterDriver()
7804          * i.e. only copy files that are newer than existing ones
7805          */
7806
7807         if (r->in.flags == 0) {
7808                 return WERR_INVALID_PARAM;
7809         }
7810
7811         if (r->in.flags != APD_COPY_NEW_FILES) {
7812                 return WERR_ACCESS_DENIED;
7813         }
7814
7815         /* FIXME */
7816         if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
7817                 /* Clever hack from Martin Zielinski <mz@seh.de>
7818                  * to allow downgrade from level 8 (Vista).
7819                  */
7820                 DEBUG(0,("%s: level %d not yet implemented\n", fn,
7821                         r->in.info_ctr->level));
7822                 return WERR_UNKNOWN_LEVEL;
7823         }
7824
7825         DEBUG(5,("Cleaning driver's information\n"));
7826         err = clean_up_driver_struct(p->mem_ctx, p, r->in.info_ctr);
7827         if (!W_ERROR_IS_OK(err))
7828                 goto done;
7829
7830         DEBUG(5,("Moving driver to final destination\n"));
7831         if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, r->in.info_ctr,
7832                                                               &err)) ) {
7833                 goto done;
7834         }
7835
7836         err = winreg_add_driver(p->mem_ctx,
7837                                 get_server_info_system(),
7838                                 p->msg_ctx,
7839                                 r->in.info_ctr,
7840                                 &driver_name,
7841                                 &version);
7842         if (!W_ERROR_IS_OK(err)) {
7843                 goto done;
7844         }
7845
7846         /*
7847          * I think this is where he DrvUpgradePrinter() hook would be
7848          * be called in a driver's interface DLL on a Windows NT 4.0/2k
7849          * server.  Right now, we just need to send ourselves a message
7850          * to update each printer bound to this driver.   --jerry
7851          */
7852
7853         if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
7854                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7855                         fn, driver_name));
7856         }
7857
7858 done:
7859         return err;
7860 }
7861
7862 /****************************************************************
7863  _spoolss_AddPrinterDriver
7864 ****************************************************************/
7865
7866 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
7867                                  struct spoolss_AddPrinterDriver *r)
7868 {
7869         struct spoolss_AddPrinterDriverEx a;
7870
7871         switch (r->in.info_ctr->level) {
7872         case 2:
7873         case 3:
7874         case 4:
7875         case 5:
7876                 break;
7877         default:
7878                 return WERR_UNKNOWN_LEVEL;
7879         }
7880
7881         a.in.servername         = r->in.servername;
7882         a.in.info_ctr           = r->in.info_ctr;
7883         a.in.flags              = APD_COPY_NEW_FILES;
7884
7885         return _spoolss_AddPrinterDriverEx(p, &a);
7886 }
7887
7888 /****************************************************************************
7889 ****************************************************************************/
7890
7891 struct _spoolss_paths {
7892         int type;
7893         const char *share;
7894         const char *dir;
7895 };
7896
7897 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
7898
7899 static const struct _spoolss_paths spoolss_paths[]= {
7900         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
7901         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
7902 };
7903
7904 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
7905                                           const char *servername,
7906                                           const char *environment,
7907                                           int component,
7908                                           char **path)
7909 {
7910         const char *pservername = NULL;
7911         const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
7912         const char *short_archi;
7913
7914         *path = NULL;
7915
7916         /* environment may be empty */
7917         if (environment && strlen(environment)) {
7918                 long_archi = environment;
7919         }
7920
7921         /* servername may be empty */
7922         if (servername && strlen(servername)) {
7923                 pservername = canon_servername(servername);
7924
7925                 if (!is_myname_or_ipaddr(pservername)) {
7926                         return WERR_INVALID_PARAM;
7927                 }
7928         }
7929
7930         if (!(short_archi = get_short_archi(long_archi))) {
7931                 return WERR_INVALID_ENVIRONMENT;
7932         }
7933
7934         switch (component) {
7935         case SPOOLSS_PRTPROCS_PATH:
7936         case SPOOLSS_DRIVER_PATH:
7937                 if (pservername) {
7938                         *path = talloc_asprintf(mem_ctx,
7939                                         "\\\\%s\\%s\\%s",
7940                                         pservername,
7941                                         spoolss_paths[component].share,
7942                                         short_archi);
7943                 } else {
7944                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
7945                                         SPOOLSS_DEFAULT_SERVER_PATH,
7946                                         spoolss_paths[component].dir,
7947                                         short_archi);
7948                 }
7949                 break;
7950         default:
7951                 return WERR_INVALID_PARAM;
7952         }
7953
7954         if (!*path) {
7955                 return WERR_NOMEM;
7956         }
7957
7958         return WERR_OK;
7959 }
7960
7961 /****************************************************************************
7962 ****************************************************************************/
7963
7964 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
7965                                           const char *servername,
7966                                           const char *environment,
7967                                           struct spoolss_DriverDirectoryInfo1 *r)
7968 {
7969         WERROR werr;
7970         char *path = NULL;
7971
7972         werr = compose_spoolss_server_path(mem_ctx,
7973                                            servername,
7974                                            environment,
7975                                            SPOOLSS_DRIVER_PATH,
7976                                            &path);
7977         if (!W_ERROR_IS_OK(werr)) {
7978                 return werr;
7979         }
7980
7981         DEBUG(4,("printer driver directory: [%s]\n", path));
7982
7983         r->directory_name = path;
7984
7985         return WERR_OK;
7986 }
7987
7988 /****************************************************************
7989  _spoolss_GetPrinterDriverDirectory
7990 ****************************************************************/
7991
7992 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
7993                                           struct spoolss_GetPrinterDriverDirectory *r)
7994 {
7995         WERROR werror;
7996
7997         /* that's an [in out] buffer */
7998
7999         if (!r->in.buffer && (r->in.offered != 0)) {
8000                 return WERR_INVALID_PARAM;
8001         }
8002
8003         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8004                 r->in.level));
8005
8006         *r->out.needed = 0;
8007
8008         /* r->in.level is ignored */
8009
8010         werror = getprinterdriverdir_level_1(p->mem_ctx,
8011                                              r->in.server,
8012                                              r->in.environment,
8013                                              &r->out.info->info1);
8014         if (!W_ERROR_IS_OK(werror)) {
8015                 TALLOC_FREE(r->out.info);
8016                 return werror;
8017         }
8018
8019         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo, 
8020                                                r->out.info, r->in.level);
8021         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8022
8023         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8024 }
8025
8026 /****************************************************************
8027  _spoolss_EnumPrinterData
8028 ****************************************************************/
8029
8030 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8031                                 struct spoolss_EnumPrinterData *r)
8032 {
8033         WERROR result;
8034         struct spoolss_EnumPrinterDataEx r2;
8035         uint32_t count;
8036         struct spoolss_PrinterEnumValues *info, *val = NULL;
8037         uint32_t needed;
8038
8039         r2.in.handle    = r->in.handle;
8040         r2.in.key_name  = "PrinterDriverData";
8041         r2.in.offered   = 0;
8042         r2.out.count    = &count;
8043         r2.out.info     = &info;
8044         r2.out.needed   = &needed;
8045
8046         result = _spoolss_EnumPrinterDataEx(p, &r2);
8047         if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8048                 r2.in.offered = needed;
8049                 result = _spoolss_EnumPrinterDataEx(p, &r2);
8050         }
8051         if (!W_ERROR_IS_OK(result)) {
8052                 return result;
8053         }
8054
8055         /*
8056          * The NT machine wants to know the biggest size of value and data
8057          *
8058          * cf: MSDN EnumPrinterData remark section
8059          */
8060
8061         if (!r->in.value_offered && !r->in.data_offered) {
8062                 uint32_t biggest_valuesize = 0;
8063                 uint32_t biggest_datasize = 0;
8064                 int i, name_length;
8065
8066                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8067
8068                 for (i=0; i<count; i++) {
8069
8070                         name_length = strlen(info[i].value_name);
8071                         if (strlen(info[i].value_name) > biggest_valuesize) {
8072                                 biggest_valuesize = name_length;
8073                         }
8074
8075                         if (info[i].data_length > biggest_datasize) {
8076                                 biggest_datasize = info[i].data_length;
8077                         }
8078
8079                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8080                                 biggest_datasize));
8081                 }
8082
8083                 /* the value is an UNICODE string but real_value_size is the length
8084                    in bytes including the trailing 0 */
8085
8086                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8087                 *r->out.data_needed  = biggest_datasize;
8088
8089                 DEBUG(6,("final values: [%d], [%d]\n",
8090                         *r->out.value_needed, *r->out.data_needed));
8091
8092                 return WERR_OK;
8093         }
8094
8095         if (r->in.enum_index < count) {
8096                 val = &info[r->in.enum_index];
8097         }
8098
8099         if (val == NULL) {
8100                 /* out_value should default to "" or else NT4 has
8101                    problems unmarshalling the response */
8102
8103                 if (r->in.value_offered) {
8104                         *r->out.value_needed = 1;
8105                         r->out.value_name = talloc_strdup(r, "");
8106                         if (!r->out.value_name) {
8107                                 return WERR_NOMEM;
8108                         }
8109                 } else {
8110                         r->out.value_name = NULL;
8111                         *r->out.value_needed = 0;
8112                 }
8113
8114                 /* the data is counted in bytes */
8115
8116                 *r->out.data_needed = r->in.data_offered;
8117
8118                 result = WERR_NO_MORE_ITEMS;
8119         } else {
8120                 /*
8121                  * the value is:
8122                  * - counted in bytes in the request
8123                  * - counted in UNICODE chars in the max reply
8124                  * - counted in bytes in the real size
8125                  *
8126                  * take a pause *before* coding not *during* coding
8127                  */
8128
8129                 /* name */
8130                 if (r->in.value_offered) {
8131                         r->out.value_name = talloc_strdup(r, val->value_name);
8132                         if (!r->out.value_name) {
8133                                 return WERR_NOMEM;
8134                         }
8135                         *r->out.value_needed = val->value_name_len;
8136                 } else {
8137                         r->out.value_name = NULL;
8138                         *r->out.value_needed = 0;
8139                 }
8140
8141                 /* type */
8142
8143                 *r->out.type = val->type;
8144
8145                 /* data - counted in bytes */
8146
8147                 /*
8148                  * See the section "Dynamically Typed Query Parameters"
8149                  * in MS-RPRN.
8150                  */
8151
8152                 if (r->out.data && val->data && val->data->data &&
8153                                 val->data_length && r->in.data_offered) {
8154                         memcpy(r->out.data, val->data->data,
8155                                 MIN(val->data_length,r->in.data_offered));
8156                 }
8157
8158                 *r->out.data_needed = val->data_length;
8159
8160                 result = WERR_OK;
8161         }
8162
8163         return result;
8164 }
8165
8166 /****************************************************************
8167  _spoolss_SetPrinterData
8168 ****************************************************************/
8169
8170 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8171                                struct spoolss_SetPrinterData *r)
8172 {
8173         struct spoolss_SetPrinterDataEx r2;
8174
8175         r2.in.handle            = r->in.handle;
8176         r2.in.key_name          = "PrinterDriverData";
8177         r2.in.value_name        = r->in.value_name;
8178         r2.in.type              = r->in.type;
8179         r2.in.data              = r->in.data;
8180         r2.in.offered           = r->in.offered;
8181
8182         return _spoolss_SetPrinterDataEx(p, &r2);
8183 }
8184
8185 /****************************************************************
8186  _spoolss_ResetPrinter
8187 ****************************************************************/
8188
8189 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8190                              struct spoolss_ResetPrinter *r)
8191 {
8192         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8193         int             snum;
8194
8195         DEBUG(5,("_spoolss_ResetPrinter\n"));
8196
8197         /*
8198          * All we do is to check to see if the handle and queue is valid.
8199          * This call really doesn't mean anything to us because we only
8200          * support RAW printing.   --jerry
8201          */
8202
8203         if (!Printer) {
8204                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8205                         OUR_HANDLE(r->in.handle)));
8206                 return WERR_BADFID;
8207         }
8208
8209         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8210                 return WERR_BADFID;
8211
8212
8213         /* blindly return success */
8214         return WERR_OK;
8215 }
8216
8217 /****************************************************************
8218  _spoolss_DeletePrinterData
8219 ****************************************************************/
8220
8221 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8222                                   struct spoolss_DeletePrinterData *r)
8223 {
8224         struct spoolss_DeletePrinterDataEx r2;
8225
8226         r2.in.handle            = r->in.handle;
8227         r2.in.key_name          = "PrinterDriverData";
8228         r2.in.value_name        = r->in.value_name;
8229
8230         return _spoolss_DeletePrinterDataEx(p, &r2);
8231 }
8232
8233 /****************************************************************
8234  _spoolss_AddForm
8235 ****************************************************************/
8236
8237 WERROR _spoolss_AddForm(struct pipes_struct *p,
8238                         struct spoolss_AddForm *r)
8239 {
8240         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8241         int snum = -1;
8242         WERROR status = WERR_OK;
8243
8244         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8245
8246         DEBUG(5,("_spoolss_AddForm\n"));
8247
8248         if (!Printer) {
8249                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8250                         OUR_HANDLE(r->in.handle)));
8251                 return WERR_BADFID;
8252         }
8253
8254         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8255            and not a printer admin, then fail */
8256
8257         if ((p->server_info->utok.uid != sec_initial_uid()) &&
8258             !security_token_has_privilege(p->server_info->ptok, SEC_PRIV_PRINT_OPERATOR) &&
8259             !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8260                                           p->server_info->info3->base.domain.string,
8261                                           NULL,
8262                                           p->server_info->ptok,
8263                                           lp_printer_admin(snum))) {
8264                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8265                 return WERR_ACCESS_DENIED;
8266         }
8267
8268         switch (form->flags) {
8269         case SPOOLSS_FORM_USER:
8270         case SPOOLSS_FORM_BUILTIN:
8271         case SPOOLSS_FORM_PRINTER:
8272                 break;
8273         default:
8274                 return WERR_INVALID_PARAM;
8275         }
8276
8277         status = winreg_printer_addform1(p->mem_ctx,
8278                                          get_server_info_system(),
8279                                          p->msg_ctx,
8280                                          form);
8281         if (!W_ERROR_IS_OK(status)) {
8282                 return status;
8283         }
8284
8285         /*
8286          * ChangeID must always be set if this is a printer
8287          */
8288         if (Printer->printer_type == SPLHND_PRINTER) {
8289                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8290                         return WERR_BADFID;
8291                 }
8292
8293                 status = winreg_printer_update_changeid(p->mem_ctx,
8294                                                         get_server_info_system(),
8295                                                         p->msg_ctx,
8296                                                         lp_const_servicename(snum));
8297                 if (!W_ERROR_IS_OK(status)) {
8298                         return status;
8299                 }
8300         }
8301
8302         return status;
8303 }
8304
8305 /****************************************************************
8306  _spoolss_DeleteForm
8307 ****************************************************************/
8308
8309 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8310                            struct spoolss_DeleteForm *r)
8311 {
8312         const char *form_name = r->in.form_name;
8313         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8314         int snum = -1;
8315         WERROR status = WERR_OK;
8316
8317         DEBUG(5,("_spoolss_DeleteForm\n"));
8318
8319         if (!Printer) {
8320                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8321                         OUR_HANDLE(r->in.handle)));
8322                 return WERR_BADFID;
8323         }
8324
8325         if ((p->server_info->utok.uid != sec_initial_uid()) &&
8326             !security_token_has_privilege(p->server_info->ptok, SEC_PRIV_PRINT_OPERATOR) &&
8327             !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8328                                           p->server_info->info3->base.domain.string,
8329                                           NULL,
8330                                           p->server_info->ptok,
8331                                           lp_printer_admin(snum))) {
8332                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8333                 return WERR_ACCESS_DENIED;
8334         }
8335
8336         status = winreg_printer_deleteform1(p->mem_ctx,
8337                                             get_server_info_system(),
8338                                             p->msg_ctx,
8339                                             form_name);
8340         if (!W_ERROR_IS_OK(status)) {
8341                 return status;
8342         }
8343
8344         /*
8345          * ChangeID must always be set if this is a printer
8346          */
8347         if (Printer->printer_type == SPLHND_PRINTER) {
8348                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8349                         return WERR_BADFID;
8350                 }
8351
8352                 status = winreg_printer_update_changeid(p->mem_ctx,
8353                                                         get_server_info_system(),
8354                                                         p->msg_ctx,
8355                                                         lp_const_servicename(snum));
8356                 if (!W_ERROR_IS_OK(status)) {
8357                         return status;
8358                 }
8359         }
8360
8361         return status;
8362 }
8363
8364 /****************************************************************
8365  _spoolss_SetForm
8366 ****************************************************************/
8367
8368 WERROR _spoolss_SetForm(struct pipes_struct *p,
8369                         struct spoolss_SetForm *r)
8370 {
8371         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8372         const char *form_name = r->in.form_name;
8373         int snum = -1;
8374         WERROR status = WERR_OK;
8375
8376         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8377
8378         DEBUG(5,("_spoolss_SetForm\n"));
8379
8380         if (!Printer) {
8381                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8382                         OUR_HANDLE(r->in.handle)));
8383                 return WERR_BADFID;
8384         }
8385
8386         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8387            and not a printer admin, then fail */
8388
8389         if ((p->server_info->utok.uid != sec_initial_uid()) &&
8390              !security_token_has_privilege(p->server_info->ptok, SEC_PRIV_PRINT_OPERATOR) &&
8391              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8392                                           p->server_info->info3->base.domain.string,
8393                                           NULL,
8394                                           p->server_info->ptok,
8395                                           lp_printer_admin(snum))) {
8396                 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8397                 return WERR_ACCESS_DENIED;
8398         }
8399
8400         status = winreg_printer_setform1(p->mem_ctx,
8401                                          get_server_info_system(),
8402                                          p->msg_ctx,
8403                                          form_name,
8404                                          form);
8405         if (!W_ERROR_IS_OK(status)) {
8406                 return status;
8407         }
8408
8409         /*
8410          * ChangeID must always be set if this is a printer
8411          */
8412         if (Printer->printer_type == SPLHND_PRINTER) {
8413                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8414                         return WERR_BADFID;
8415                 }
8416
8417                 status = winreg_printer_update_changeid(p->mem_ctx,
8418                                                         get_server_info_system(),
8419                                                         p->msg_ctx,
8420                                                         lp_const_servicename(snum));
8421                 if (!W_ERROR_IS_OK(status)) {
8422                         return status;
8423                 }
8424         }
8425
8426         return status;
8427 }
8428
8429 /****************************************************************************
8430  fill_print_processor1
8431 ****************************************************************************/
8432
8433 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8434                                     struct spoolss_PrintProcessorInfo1 *r,
8435                                     const char *print_processor_name)
8436 {
8437         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8438         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8439
8440         return WERR_OK;
8441 }
8442
8443 /****************************************************************************
8444  enumprintprocessors level 1.
8445 ****************************************************************************/
8446
8447 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8448                                           union spoolss_PrintProcessorInfo **info_p,
8449                                           uint32_t *count)
8450 {
8451         union spoolss_PrintProcessorInfo *info;
8452         WERROR result;
8453
8454         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8455         W_ERROR_HAVE_NO_MEMORY(info);
8456
8457         *count = 1;
8458
8459         result = fill_print_processor1(info, &info[0].info1, "winprint");
8460         if (!W_ERROR_IS_OK(result)) {
8461                 goto out;
8462         }
8463
8464  out:
8465         if (!W_ERROR_IS_OK(result)) {
8466                 TALLOC_FREE(info);
8467                 *count = 0;
8468                 return result;
8469         }
8470
8471         *info_p = info;
8472
8473         return WERR_OK;
8474 }
8475
8476 /****************************************************************
8477  _spoolss_EnumPrintProcessors
8478 ****************************************************************/
8479
8480 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
8481                                     struct spoolss_EnumPrintProcessors *r)
8482 {
8483         WERROR result;
8484
8485         /* that's an [in out] buffer */
8486
8487         if (!r->in.buffer && (r->in.offered != 0)) {
8488                 return WERR_INVALID_PARAM;
8489         }
8490
8491         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8492
8493         /*
8494          * Enumerate the print processors ...
8495          *
8496          * Just reply with "winprint", to keep NT happy
8497          * and I can use my nice printer checker.
8498          */
8499
8500         *r->out.count = 0;
8501         *r->out.needed = 0;
8502         *r->out.info = NULL;
8503
8504         if (!get_short_archi(r->in.environment)) {
8505                 return WERR_INVALID_ENVIRONMENT;
8506         }
8507
8508         switch (r->in.level) {
8509         case 1:
8510                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8511                                                      r->out.count);
8512                 break;
8513         default:
8514                 return WERR_UNKNOWN_LEVEL;
8515         }
8516
8517         if (!W_ERROR_IS_OK(result)) {
8518                 return result;
8519         }
8520
8521         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8522                                                      spoolss_EnumPrintProcessors,
8523                                                      *r->out.info, r->in.level,
8524                                                      *r->out.count);
8525         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8526         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8527
8528         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8529 }
8530
8531 /****************************************************************************
8532  fill_printprocdatatype1
8533 ****************************************************************************/
8534
8535 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8536                                       struct spoolss_PrintProcDataTypesInfo1 *r,
8537                                       const char *name_array)
8538 {
8539         r->name_array = talloc_strdup(mem_ctx, name_array);
8540         W_ERROR_HAVE_NO_MEMORY(r->name_array);
8541
8542         return WERR_OK;
8543 }
8544
8545 /****************************************************************************
8546  enumprintprocdatatypes level 1.
8547 ****************************************************************************/
8548
8549 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8550                                              union spoolss_PrintProcDataTypesInfo **info_p,
8551                                              uint32_t *count)
8552 {
8553         WERROR result;
8554         union spoolss_PrintProcDataTypesInfo *info;
8555
8556         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8557         W_ERROR_HAVE_NO_MEMORY(info);
8558
8559         *count = 1;
8560
8561         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8562         if (!W_ERROR_IS_OK(result)) {
8563                 goto out;
8564         }
8565
8566  out:
8567         if (!W_ERROR_IS_OK(result)) {
8568                 TALLOC_FREE(info);
8569                 *count = 0;
8570                 return result;
8571         }
8572
8573         *info_p = info;
8574
8575         return WERR_OK;
8576 }
8577
8578 /****************************************************************
8579  _spoolss_EnumPrintProcDataTypes
8580 ****************************************************************/
8581
8582 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
8583                                        struct spoolss_EnumPrintProcDataTypes *r)
8584 {
8585         WERROR result;
8586
8587         /* that's an [in out] buffer */
8588
8589         if (!r->in.buffer && (r->in.offered != 0)) {
8590                 return WERR_INVALID_PARAM;
8591         }
8592
8593         DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8594
8595         *r->out.count = 0;
8596         *r->out.needed = 0;
8597         *r->out.info = NULL;
8598
8599         switch (r->in.level) {
8600         case 1:
8601                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8602                                                         r->out.count);
8603                 break;
8604         default:
8605                 return WERR_UNKNOWN_LEVEL;
8606         }
8607
8608         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8609                                                      spoolss_EnumPrintProcDataTypes, 
8610                                                      *r->out.info, r->in.level,
8611                                                      *r->out.count);
8612         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8613         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8614
8615         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8616 }
8617
8618 /****************************************************************************
8619  fill_monitor_1
8620 ****************************************************************************/
8621
8622 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8623                              struct spoolss_MonitorInfo1 *r,
8624                              const char *monitor_name)
8625 {
8626         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8627         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8628
8629         return WERR_OK;
8630 }
8631
8632 /****************************************************************************
8633  fill_monitor_2
8634 ****************************************************************************/
8635
8636 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8637                              struct spoolss_MonitorInfo2 *r,
8638                              const char *monitor_name,
8639                              const char *environment,
8640                              const char *dll_name)
8641 {
8642         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8643         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8644         r->environment                  = talloc_strdup(mem_ctx, environment);
8645         W_ERROR_HAVE_NO_MEMORY(r->environment);
8646         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
8647         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8648
8649         return WERR_OK;
8650 }
8651
8652 /****************************************************************************
8653  enumprintmonitors level 1.
8654 ****************************************************************************/
8655
8656 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8657                                         union spoolss_MonitorInfo **info_p,
8658                                         uint32_t *count)
8659 {
8660         union spoolss_MonitorInfo *info;
8661         WERROR result = WERR_OK;
8662
8663         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8664         W_ERROR_HAVE_NO_MEMORY(info);
8665
8666         *count = 2;
8667
8668         result = fill_monitor_1(info, &info[0].info1,
8669                                 SPL_LOCAL_PORT);
8670         if (!W_ERROR_IS_OK(result)) {
8671                 goto out;
8672         }
8673
8674         result = fill_monitor_1(info, &info[1].info1,
8675                                 SPL_TCPIP_PORT);
8676         if (!W_ERROR_IS_OK(result)) {
8677                 goto out;
8678         }
8679
8680 out:
8681         if (!W_ERROR_IS_OK(result)) {
8682                 TALLOC_FREE(info);
8683                 *count = 0;
8684                 return result;
8685         }
8686
8687         *info_p = info;
8688
8689         return WERR_OK;
8690 }
8691
8692 /****************************************************************************
8693  enumprintmonitors level 2.
8694 ****************************************************************************/
8695
8696 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8697                                         union spoolss_MonitorInfo **info_p,
8698                                         uint32_t *count)
8699 {
8700         union spoolss_MonitorInfo *info;
8701         WERROR result = WERR_OK;
8702
8703         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8704         W_ERROR_HAVE_NO_MEMORY(info);
8705
8706         *count = 2;
8707
8708         result = fill_monitor_2(info, &info[0].info2,
8709                                 SPL_LOCAL_PORT,
8710                                 "Windows NT X86", /* FIXME */
8711                                 "localmon.dll");
8712         if (!W_ERROR_IS_OK(result)) {
8713                 goto out;
8714         }
8715
8716         result = fill_monitor_2(info, &info[1].info2,
8717                                 SPL_TCPIP_PORT,
8718                                 "Windows NT X86", /* FIXME */
8719                                 "tcpmon.dll");
8720         if (!W_ERROR_IS_OK(result)) {
8721                 goto out;
8722         }
8723
8724 out:
8725         if (!W_ERROR_IS_OK(result)) {
8726                 TALLOC_FREE(info);
8727                 *count = 0;
8728                 return result;
8729         }
8730
8731         *info_p = info;
8732
8733         return WERR_OK;
8734 }
8735
8736 /****************************************************************
8737  _spoolss_EnumMonitors
8738 ****************************************************************/
8739
8740 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
8741                              struct spoolss_EnumMonitors *r)
8742 {
8743         WERROR result;
8744
8745         /* that's an [in out] buffer */
8746
8747         if (!r->in.buffer && (r->in.offered != 0)) {
8748                 return WERR_INVALID_PARAM;
8749         }
8750
8751         DEBUG(5,("_spoolss_EnumMonitors\n"));
8752
8753         /*
8754          * Enumerate the print monitors ...
8755          *
8756          * Just reply with "Local Port", to keep NT happy
8757          * and I can use my nice printer checker.
8758          */
8759
8760         *r->out.count = 0;
8761         *r->out.needed = 0;
8762         *r->out.info = NULL;
8763
8764         switch (r->in.level) {
8765         case 1:
8766                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8767                                                    r->out.count);
8768                 break;
8769         case 2:
8770                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8771                                                    r->out.count);
8772                 break;
8773         default:
8774                 return WERR_UNKNOWN_LEVEL;
8775         }
8776
8777         if (!W_ERROR_IS_OK(result)) {
8778                 return result;
8779         }
8780
8781         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8782                                                      spoolss_EnumMonitors, 
8783                                                      *r->out.info, r->in.level,
8784                                                      *r->out.count);
8785         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8786         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8787
8788         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8789 }
8790
8791 /****************************************************************************
8792 ****************************************************************************/
8793
8794 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8795                              const print_queue_struct *queue,
8796                              int count, int snum,
8797                              struct spoolss_PrinterInfo2 *pinfo2,
8798                              uint32_t jobid,
8799                              struct spoolss_JobInfo1 *r)
8800 {
8801         int i = 0;
8802         bool found = false;
8803
8804         for (i=0; i<count; i++) {
8805                 if (queue[i].job == (int)jobid) {
8806                         found = true;
8807                         break;
8808                 }
8809         }
8810
8811         if (found == false) {
8812                 /* NT treats not found as bad param... yet another bad choice */
8813                 return WERR_INVALID_PARAM;
8814         }
8815
8816         return fill_job_info1(mem_ctx,
8817                               r,
8818                               &queue[i],
8819                               i,
8820                               snum,
8821                               pinfo2);
8822 }
8823
8824 /****************************************************************************
8825 ****************************************************************************/
8826
8827 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
8828                              const print_queue_struct *queue,
8829                              int count, int snum,
8830                              struct spoolss_PrinterInfo2 *pinfo2,
8831                              uint32_t jobid,
8832                              struct spoolss_JobInfo2 *r)
8833 {
8834         int i = 0;
8835         bool found = false;
8836         struct spoolss_DeviceMode *devmode;
8837         WERROR result;
8838
8839         for (i=0; i<count; i++) {
8840                 if (queue[i].job == (int)jobid) {
8841                         found = true;
8842                         break;
8843                 }
8844         }
8845
8846         if (found == false) {
8847                 /* NT treats not found as bad param... yet another bad
8848                    choice */
8849                 return WERR_INVALID_PARAM;
8850         }
8851
8852         /*
8853          * if the print job does not have a DEVMODE associated with it,
8854          * just use the one for the printer. A NULL devicemode is not
8855          *  a failure condition
8856          */
8857
8858         devmode = print_job_devmode(lp_const_servicename(snum), jobid);
8859         if (!devmode) {
8860                 result = spoolss_create_default_devmode(mem_ctx,
8861                                                 pinfo2->printername,
8862                                                 &devmode);
8863                 if (!W_ERROR_IS_OK(result)) {
8864                         DEBUG(3, ("Can't proceed w/o a devmode!"));
8865                         return result;
8866                 }
8867         }
8868
8869         return fill_job_info2(mem_ctx,
8870                               r,
8871                               &queue[i],
8872                               i,
8873                               snum,
8874                               pinfo2,
8875                               devmode);
8876 }
8877
8878 /****************************************************************
8879  _spoolss_GetJob
8880 ****************************************************************/
8881
8882 WERROR _spoolss_GetJob(struct pipes_struct *p,
8883                        struct spoolss_GetJob *r)
8884 {
8885         WERROR result = WERR_OK;
8886         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
8887         int snum;
8888         int count;
8889         print_queue_struct      *queue = NULL;
8890         print_status_struct prt_status;
8891
8892         /* that's an [in out] buffer */
8893
8894         if (!r->in.buffer && (r->in.offered != 0)) {
8895                 return WERR_INVALID_PARAM;
8896         }
8897
8898         DEBUG(5,("_spoolss_GetJob\n"));
8899
8900         *r->out.needed = 0;
8901
8902         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8903                 return WERR_BADFID;
8904         }
8905
8906         result = winreg_get_printer(p->mem_ctx,
8907                                     get_server_info_system(),
8908                                     p->msg_ctx,
8909                                     NULL,
8910                                     lp_const_servicename(snum),
8911                                     &pinfo2);
8912         if (!W_ERROR_IS_OK(result)) {
8913                 return result;
8914         }
8915
8916         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
8917
8918         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8919                      count, prt_status.status, prt_status.message));
8920
8921         switch (r->in.level) {
8922         case 1:
8923                 result = getjob_level_1(p->mem_ctx,
8924                                         queue, count, snum, pinfo2,
8925                                         r->in.job_id, &r->out.info->info1);
8926                 break;
8927         case 2:
8928                 result = getjob_level_2(p->mem_ctx,
8929                                         queue, count, snum, pinfo2,
8930                                         r->in.job_id, &r->out.info->info2);
8931                 break;
8932         default:
8933                 result = WERR_UNKNOWN_LEVEL;
8934                 break;
8935         }
8936
8937         SAFE_FREE(queue);
8938         TALLOC_FREE(pinfo2);
8939
8940         if (!W_ERROR_IS_OK(result)) {
8941                 TALLOC_FREE(r->out.info);
8942                 return result;
8943         }
8944
8945         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
8946                                                                                    r->in.level);
8947         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8948
8949         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8950 }
8951
8952 /****************************************************************
8953  _spoolss_GetPrinterDataEx
8954 ****************************************************************/
8955
8956 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
8957                                  struct spoolss_GetPrinterDataEx *r)
8958 {
8959
8960         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8961         const char *printer;
8962         int                     snum = 0;
8963         WERROR result = WERR_OK;
8964         DATA_BLOB blob;
8965         enum winreg_Type val_type;
8966         uint8_t *val_data;
8967         uint32_t val_size;
8968
8969
8970         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
8971
8972         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
8973                 r->in.key_name, r->in.value_name));
8974
8975         /* in case of problem, return some default values */
8976
8977         *r->out.needed  = 0;
8978         *r->out.type    = REG_NONE;
8979
8980         if (!Printer) {
8981                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8982                         OUR_HANDLE(r->in.handle)));
8983                 result = WERR_BADFID;
8984                 goto done;
8985         }
8986
8987         /* Is the handle to a printer or to the server? */
8988
8989         if (Printer->printer_type == SPLHND_SERVER) {
8990
8991                 union spoolss_PrinterData data;
8992
8993                 result = getprinterdata_printer_server(p->mem_ctx,
8994                                                        r->in.value_name,
8995                                                        r->out.type,
8996                                                        &data);
8997                 if (!W_ERROR_IS_OK(result)) {
8998                         return result;
8999                 }
9000
9001                 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
9002                                                   *r->out.type, &data);
9003                 if (!W_ERROR_IS_OK(result)) {
9004                         return result;
9005                 }
9006
9007                 *r->out.needed = blob.length;
9008
9009                 if (r->in.offered >= *r->out.needed) {
9010                         memcpy(r->out.data, blob.data, blob.length);
9011                 }
9012
9013                 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9014         }
9015
9016         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9017                 return WERR_BADFID;
9018         }
9019         printer = lp_const_servicename(snum);
9020
9021         /* check to see if the keyname is valid */
9022         if (!strlen(r->in.key_name)) {
9023                 return WERR_INVALID_PARAM;
9024         }
9025
9026         /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9027         if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9028             strequal(r->in.value_name, "ChangeId")) {
9029                 *r->out.type = REG_DWORD;
9030                 *r->out.needed = 4;
9031                 if (r->in.offered >= *r->out.needed) {
9032                         uint32_t changeid = 0;
9033
9034                         result = winreg_printer_get_changeid(p->mem_ctx,
9035                                                              get_server_info_system(),
9036                                                              p->msg_ctx,
9037                                                              printer,
9038                                                              &changeid);
9039                         if (!W_ERROR_IS_OK(result)) {
9040                                 return result;
9041                         }
9042
9043                         SIVAL(r->out.data, 0, changeid);
9044                         result = WERR_OK;
9045                 }
9046                 goto done;
9047         }
9048
9049         result = winreg_get_printer_dataex(p->mem_ctx,
9050                                            get_server_info_system(),
9051                                            p->msg_ctx,
9052                                            printer,
9053                                            r->in.key_name,
9054                                            r->in.value_name,
9055                                            &val_type,
9056                                            &val_data,
9057                                            &val_size);
9058         if (!W_ERROR_IS_OK(result)) {
9059                 return result;
9060         }
9061
9062         *r->out.needed = val_size;
9063         *r->out.type = val_type;
9064
9065         if (r->in.offered >= *r->out.needed) {
9066                 memcpy(r->out.data, val_data, val_size);
9067         }
9068
9069  done:
9070         *r->out.type    = SPOOLSS_BUFFER_OK(*r->out.type, REG_NONE);
9071         r->out.data     = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
9072
9073         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9074 }
9075
9076 /****************************************************************
9077  _spoolss_SetPrinterDataEx
9078 ****************************************************************/
9079
9080 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9081                                  struct spoolss_SetPrinterDataEx *r)
9082 {
9083         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9084         int                     snum = 0;
9085         WERROR                  result = WERR_OK;
9086         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9087         char                    *oid_string;
9088
9089         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9090
9091         /* From MSDN documentation of SetPrinterDataEx: pass request to
9092            SetPrinterData if key is "PrinterDriverData" */
9093
9094         if (!Printer) {
9095                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9096                         OUR_HANDLE(r->in.handle)));
9097                 return WERR_BADFID;
9098         }
9099
9100         if (Printer->printer_type == SPLHND_SERVER) {
9101                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9102                         "Not implemented for server handles yet\n"));
9103                 return WERR_INVALID_PARAM;
9104         }
9105
9106         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9107                 return WERR_BADFID;
9108         }
9109
9110         /*
9111          * Access check : NT returns "access denied" if you make a
9112          * SetPrinterData call without the necessary privildge.
9113          * we were originally returning OK if nothing changed
9114          * which made Win2k issue **a lot** of SetPrinterData
9115          * when connecting to a printer  --jerry
9116          */
9117
9118         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9119                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9120                         "change denied by handle access permissions\n"));
9121                 return WERR_ACCESS_DENIED;
9122         }
9123
9124         result = winreg_get_printer(Printer,
9125                                     get_server_info_system(),
9126                                     p->msg_ctx,
9127                                     Printer->servername,
9128                                     lp_servicename(snum),
9129                                     &pinfo2);
9130         if (!W_ERROR_IS_OK(result)) {
9131                 return result;
9132         }
9133
9134         /* check for OID in valuename */
9135
9136         oid_string = strchr(r->in.value_name, ',');
9137         if (oid_string) {
9138                 *oid_string = '\0';
9139                 oid_string++;
9140         }
9141
9142         /* save the registry data */
9143
9144         result = winreg_set_printer_dataex(p->mem_ctx,
9145                                            get_server_info_system(),
9146                                            p->msg_ctx,
9147                                            pinfo2->sharename,
9148                                            r->in.key_name,
9149                                            r->in.value_name,
9150                                            r->in.type,
9151                                            r->in.data,
9152                                            r->in.offered);
9153
9154         if (W_ERROR_IS_OK(result)) {
9155                 /* save the OID if one was specified */
9156                 if (oid_string) {
9157                         char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9158                                 r->in.key_name, SPOOL_OID_KEY);
9159                         if (!str) {
9160                                 result = WERR_NOMEM;
9161                                 goto done;
9162                         }
9163
9164                         /*
9165                          * I'm not checking the status here on purpose.  Don't know
9166                          * if this is right, but I'm returning the status from the
9167                          * previous set_printer_dataex() call.  I have no idea if
9168                          * this is right.    --jerry
9169                          */
9170                         winreg_set_printer_dataex(p->mem_ctx,
9171                                                   get_server_info_system(),
9172                                                   p->msg_ctx,
9173                                                   pinfo2->sharename,
9174                                                   str,
9175                                                   r->in.value_name,
9176                                                   REG_SZ,
9177                                                   (uint8_t *) oid_string,
9178                                                   strlen(oid_string) + 1);
9179                 }
9180
9181                 result = winreg_printer_update_changeid(p->mem_ctx,
9182                                                         get_server_info_system(),
9183                                                         p->msg_ctx,
9184                                                         lp_const_servicename(snum));
9185
9186         }
9187
9188 done:
9189         talloc_free(pinfo2);
9190         return result;
9191 }
9192
9193 /****************************************************************
9194  _spoolss_DeletePrinterDataEx
9195 ****************************************************************/
9196
9197 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9198                                     struct spoolss_DeletePrinterDataEx *r)
9199 {
9200         const char *printer;
9201         int             snum=0;
9202         WERROR          status = WERR_OK;
9203         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9204
9205         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9206
9207         if (!Printer) {
9208                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9209                         "Invalid handle (%s:%u:%u).\n",
9210                         OUR_HANDLE(r->in.handle)));
9211                 return WERR_BADFID;
9212         }
9213
9214         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9215                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9216                         "printer properties change denied by handle\n"));
9217                 return WERR_ACCESS_DENIED;
9218         }
9219
9220         if (!r->in.value_name || !r->in.key_name) {
9221                 return WERR_NOMEM;
9222         }
9223
9224         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9225                 return WERR_BADFID;
9226         }
9227         printer = lp_const_servicename(snum);
9228
9229         status = winreg_delete_printer_dataex(p->mem_ctx,
9230                                               get_server_info_system(),
9231                                               p->msg_ctx,
9232                                               printer,
9233                                               r->in.key_name,
9234                                               r->in.value_name);
9235         if (W_ERROR_IS_OK(status)) {
9236                 status = winreg_printer_update_changeid(p->mem_ctx,
9237                                                         get_server_info_system(),
9238                                                         p->msg_ctx,
9239                                                         printer);
9240         }
9241
9242         return status;
9243 }
9244
9245 /****************************************************************
9246  _spoolss_EnumPrinterKey
9247 ****************************************************************/
9248
9249 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9250                                struct spoolss_EnumPrinterKey *r)
9251 {
9252         uint32_t        num_keys;
9253         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9254         int             snum = 0;
9255         WERROR          result = WERR_BADFILE;
9256         const char **array = NULL;
9257         DATA_BLOB blob;
9258
9259         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9260
9261         if (!Printer) {
9262                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9263                         OUR_HANDLE(r->in.handle)));
9264                 return WERR_BADFID;
9265         }
9266
9267         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9268                 return WERR_BADFID;
9269         }
9270
9271         result = winreg_enum_printer_key(p->mem_ctx,
9272                                          get_server_info_system(),
9273                                          p->msg_ctx,
9274                                          lp_const_servicename(snum),
9275                                          r->in.key_name,
9276                                          &num_keys,
9277                                          &array);
9278         if (!W_ERROR_IS_OK(result)) {
9279                 goto done;
9280         }
9281
9282         if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9283                 result = WERR_NOMEM;
9284                 goto done;
9285         }
9286
9287         *r->out._ndr_size = r->in.offered / 2;
9288         *r->out.needed = blob.length;
9289
9290         if (r->in.offered < *r->out.needed) {
9291                 result = WERR_MORE_DATA;
9292         } else {
9293                 result = WERR_OK;
9294                 r->out.key_buffer->string_array = array;
9295         }
9296
9297  done:
9298         if (!W_ERROR_IS_OK(result)) {
9299                 TALLOC_FREE(array);
9300                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9301                         *r->out.needed = 0;
9302                 }
9303         }
9304
9305         return result;
9306 }
9307
9308 /****************************************************************
9309  _spoolss_DeletePrinterKey
9310 ****************************************************************/
9311
9312 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9313                                  struct spoolss_DeletePrinterKey *r)
9314 {
9315         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9316         int                     snum=0;
9317         WERROR                  status;
9318         const char *printer;
9319
9320         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9321
9322         if (!Printer) {
9323                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9324                         OUR_HANDLE(r->in.handle)));
9325                 return WERR_BADFID;
9326         }
9327
9328         /* if keyname == NULL, return error */
9329         if ( !r->in.key_name )
9330                 return WERR_INVALID_PARAM;
9331
9332         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9333                 return WERR_BADFID;
9334         }
9335
9336         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9337                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9338                         "printer properties change denied by handle\n"));
9339                 return WERR_ACCESS_DENIED;
9340         }
9341
9342         printer = lp_const_servicename(snum);
9343
9344         /* delete the key and all subkeys */
9345         status = winreg_delete_printer_key(p->mem_ctx,
9346                                            get_server_info_system(),
9347                                            p->msg_ctx,
9348                                            printer,
9349                                            r->in.key_name);
9350         if (W_ERROR_IS_OK(status)) {
9351                 status = winreg_printer_update_changeid(p->mem_ctx,
9352                                                         get_server_info_system(),
9353                                                         p->msg_ctx,
9354                                                         printer);
9355         }
9356
9357         return status;
9358 }
9359
9360 /****************************************************************
9361  _spoolss_EnumPrinterDataEx
9362 ****************************************************************/
9363
9364 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
9365                                   struct spoolss_EnumPrinterDataEx *r)
9366 {
9367         uint32_t        count = 0;
9368         struct spoolss_PrinterEnumValues *info = NULL;
9369         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9370         int             snum;
9371         WERROR          result;
9372
9373         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9374
9375         *r->out.count = 0;
9376         *r->out.needed = 0;
9377         *r->out.info = NULL;
9378
9379         if (!Printer) {
9380                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9381                         OUR_HANDLE(r->in.handle)));
9382                 return WERR_BADFID;
9383         }
9384
9385         /*
9386          * first check for a keyname of NULL or "".  Win2k seems to send
9387          * this a lot and we should send back WERR_INVALID_PARAM
9388          * no need to spend time looking up the printer in this case.
9389          * --jerry
9390          */
9391
9392         if (!strlen(r->in.key_name)) {
9393                 result = WERR_INVALID_PARAM;
9394                 goto done;
9395         }
9396
9397         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9398                 return WERR_BADFID;
9399         }
9400
9401         /* now look for a match on the key name */
9402         result = winreg_enum_printer_dataex(p->mem_ctx,
9403                                             get_server_info_system(),
9404                                             p->msg_ctx,
9405                                             lp_const_servicename(snum),
9406                                             r->in.key_name,
9407                                             &count,
9408                                             &info);
9409         if (!W_ERROR_IS_OK(result)) {
9410                 goto done;
9411         }
9412
9413 #if 0 /* FIXME - gd */
9414         /* housekeeping information in the reply */
9415
9416         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9417          * the hand marshalled container size is a multiple
9418          * of 4 bytes for RPC alignment.
9419          */
9420
9421         if (needed % 4) {
9422                 needed += 4-(needed % 4);
9423         }
9424 #endif
9425         *r->out.count   = count;
9426         *r->out.info    = info;
9427
9428  done:
9429         if (!W_ERROR_IS_OK(result)) {
9430                 return result;
9431         }
9432
9433         *r->out.needed  = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9434                                                spoolss_EnumPrinterDataEx, 
9435                                                *r->out.info,
9436                                                *r->out.count);
9437         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9438         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9439
9440         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9441 }
9442
9443 /****************************************************************************
9444 ****************************************************************************/
9445
9446 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9447                                                  const char *servername,
9448                                                  const char *environment,
9449                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
9450 {
9451         WERROR werr;
9452         char *path = NULL;
9453
9454         werr = compose_spoolss_server_path(mem_ctx,
9455                                            servername,
9456                                            environment,
9457                                            SPOOLSS_PRTPROCS_PATH,
9458                                            &path);
9459         if (!W_ERROR_IS_OK(werr)) {
9460                 return werr;
9461         }
9462
9463         DEBUG(4,("print processor directory: [%s]\n", path));
9464
9465         r->directory_name = path;
9466
9467         return WERR_OK;
9468 }
9469
9470 /****************************************************************
9471  _spoolss_GetPrintProcessorDirectory
9472 ****************************************************************/
9473
9474 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
9475                                            struct spoolss_GetPrintProcessorDirectory *r)
9476 {
9477         WERROR result;
9478
9479         /* that's an [in out] buffer */
9480
9481         if (!r->in.buffer && (r->in.offered != 0)) {
9482                 return WERR_INVALID_PARAM;
9483         }
9484
9485         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9486                 r->in.level));
9487
9488         *r->out.needed = 0;
9489
9490         /* r->in.level is ignored */
9491
9492         /* We always should reply with a local print processor directory so that
9493          * users are not forced to have a [prnproc$] share on the Samba spoolss
9494          * server - Guenther */
9495
9496         result = getprintprocessordirectory_level_1(p->mem_ctx,
9497                                                     NULL, /* r->in.server */
9498                                                     r->in.environment,
9499                                                     &r->out.info->info1);
9500         if (!W_ERROR_IS_OK(result)) {
9501                 TALLOC_FREE(r->out.info);
9502                 return result;
9503         }
9504
9505         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
9506                                                                                    r->out.info, r->in.level);
9507         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9508
9509         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9510 }
9511
9512 /*******************************************************************
9513  ********************************************************************/
9514
9515 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9516                                const char *dllname)
9517 {
9518         enum ndr_err_code ndr_err;
9519         struct spoolss_MonitorUi ui;
9520
9521         ui.dll_name = dllname;
9522
9523         ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
9524                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9525         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9526                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9527         }
9528         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9529 }
9530
9531 /*******************************************************************
9532  Streams the monitor UI DLL name in UNICODE
9533 *******************************************************************/
9534
9535 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9536                                struct security_token *token, DATA_BLOB *in,
9537                                DATA_BLOB *out, uint32_t *needed)
9538 {
9539         const char *dllname = "tcpmonui.dll";
9540
9541         *needed = (strlen(dllname)+1) * 2;
9542
9543         if (out->length < *needed) {
9544                 return WERR_INSUFFICIENT_BUFFER;
9545         }
9546
9547         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9548                 return WERR_NOMEM;
9549         }
9550
9551         return WERR_OK;
9552 }
9553
9554 /*******************************************************************
9555  ********************************************************************/
9556
9557 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9558                              struct spoolss_PortData1 *port1,
9559                              const DATA_BLOB *buf)
9560 {
9561         enum ndr_err_code ndr_err;
9562         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
9563                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9564         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9565                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9566         }
9567         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9568 }
9569
9570 /*******************************************************************
9571  ********************************************************************/
9572
9573 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9574                              struct spoolss_PortData2 *port2,
9575                              const DATA_BLOB *buf)
9576 {
9577         enum ndr_err_code ndr_err;
9578         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
9579                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9580         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9581                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9582         }
9583         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9584 }
9585
9586 /*******************************************************************
9587  Create a new TCP/IP port
9588 *******************************************************************/
9589
9590 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9591                              struct security_token *token, DATA_BLOB *in,
9592                              DATA_BLOB *out, uint32_t *needed)
9593 {
9594         struct spoolss_PortData1 port1;
9595         struct spoolss_PortData2 port2;
9596         char *device_uri = NULL;
9597         uint32_t version;
9598
9599         const char *portname;
9600         const char *hostaddress;
9601         const char *queue;
9602         uint32_t port_number;
9603         uint32_t protocol;
9604
9605         /* peek for spoolss_PortData version */
9606
9607         if (!in || (in->length < (128 + 4))) {
9608                 return WERR_GENERAL_FAILURE;
9609         }
9610
9611         version = IVAL(in->data, 128);
9612
9613         switch (version) {
9614                 case 1:
9615                         ZERO_STRUCT(port1);
9616
9617                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
9618                                 return WERR_NOMEM;
9619                         }
9620
9621                         portname        = port1.portname;
9622                         hostaddress     = port1.hostaddress;
9623                         queue           = port1.queue;
9624                         protocol        = port1.protocol;
9625                         port_number     = port1.port_number;
9626
9627                         break;
9628                 case 2:
9629                         ZERO_STRUCT(port2);
9630
9631                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
9632                                 return WERR_NOMEM;
9633                         }
9634
9635                         portname        = port2.portname;
9636                         hostaddress     = port2.hostaddress;
9637                         queue           = port2.queue;
9638                         protocol        = port2.protocol;
9639                         port_number     = port2.port_number;
9640
9641                         break;
9642                 default:
9643                         DEBUG(1,("xcvtcp_addport: "
9644                                 "unknown version of port_data: %d\n", version));
9645                         return WERR_UNKNOWN_PORT;
9646         }
9647
9648         /* create the device URI and call the add_port_hook() */
9649
9650         switch (protocol) {
9651         case PROTOCOL_RAWTCP_TYPE:
9652                 device_uri = talloc_asprintf(mem_ctx,
9653                                 "socket://%s:%d/", hostaddress,
9654                                 port_number);
9655                 break;
9656
9657         case PROTOCOL_LPR_TYPE:
9658                 device_uri = talloc_asprintf(mem_ctx,
9659                         "lpr://%s/%s", hostaddress, queue );
9660                 break;
9661
9662         default:
9663                 return WERR_UNKNOWN_PORT;
9664         }
9665
9666         if (!device_uri) {
9667                 return WERR_NOMEM;
9668         }
9669
9670         return add_port_hook(mem_ctx, token, portname, device_uri);
9671 }
9672
9673 /*******************************************************************
9674 *******************************************************************/
9675
9676 struct xcv_api_table xcvtcp_cmds[] = {
9677         { "MonitorUI",  xcvtcp_monitorui },
9678         { "AddPort",    xcvtcp_addport},
9679         { NULL,         NULL }
9680 };
9681
9682 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9683                                      struct security_token *token, const char *command,
9684                                      DATA_BLOB *inbuf,
9685                                      DATA_BLOB *outbuf,
9686                                      uint32_t *needed )
9687 {
9688         int i;
9689
9690         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9691
9692         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9693                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9694                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9695         }
9696
9697         return WERR_BADFUNC;
9698 }
9699
9700 /*******************************************************************
9701 *******************************************************************/
9702 #if 0   /* don't support management using the "Local Port" monitor */
9703
9704 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9705                                  struct security_token *token, DATA_BLOB *in,
9706                                  DATA_BLOB *out, uint32_t *needed)
9707 {
9708         const char *dllname = "localui.dll";
9709
9710         *needed = (strlen(dllname)+1) * 2;
9711
9712         if (out->length < *needed) {
9713                 return WERR_INSUFFICIENT_BUFFER;
9714         }
9715
9716         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9717                 return WERR_NOMEM;
9718         }
9719
9720         return WERR_OK;
9721 }
9722
9723 /*******************************************************************
9724 *******************************************************************/
9725
9726 struct xcv_api_table xcvlocal_cmds[] = {
9727         { "MonitorUI",  xcvlocal_monitorui },
9728         { NULL,         NULL }
9729 };
9730 #else
9731 struct xcv_api_table xcvlocal_cmds[] = {
9732         { NULL,         NULL }
9733 };
9734 #endif
9735
9736
9737
9738 /*******************************************************************
9739 *******************************************************************/
9740
9741 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9742                                        struct security_token *token, const char *command,
9743                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9744                                        uint32_t *needed)
9745 {
9746         int i;
9747
9748         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9749
9750         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9751                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9752                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9753         }
9754         return WERR_BADFUNC;
9755 }
9756
9757 /****************************************************************
9758  _spoolss_XcvData
9759 ****************************************************************/
9760
9761 WERROR _spoolss_XcvData(struct pipes_struct *p,
9762                         struct spoolss_XcvData *r)
9763 {
9764         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9765         DATA_BLOB out_data = data_blob_null;
9766         WERROR werror;
9767
9768         if (!Printer) {
9769                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9770                         OUR_HANDLE(r->in.handle)));
9771                 return WERR_BADFID;
9772         }
9773
9774         /* Has to be a handle to the TCP/IP port monitor */
9775
9776         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9777                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9778                 return WERR_BADFID;
9779         }
9780
9781         /* requires administrative access to the server */
9782
9783         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9784                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9785                 return WERR_ACCESS_DENIED;
9786         }
9787
9788         /* Allocate the outgoing buffer */
9789
9790         if (r->in.out_data_size) {
9791                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9792                 if (out_data.data == NULL) {
9793                         return WERR_NOMEM;
9794                 }
9795         }
9796
9797         switch ( Printer->printer_type ) {
9798         case SPLHND_PORTMON_TCP:
9799                 werror = process_xcvtcp_command(p->mem_ctx,
9800                                                 p->server_info->ptok,
9801                                                 r->in.function_name,
9802                                                 &r->in.in_data, &out_data,
9803                                                 r->out.needed);
9804                 break;
9805         case SPLHND_PORTMON_LOCAL:
9806                 werror = process_xcvlocal_command(p->mem_ctx,
9807                                                   p->server_info->ptok,
9808                                                   r->in.function_name,
9809                                                   &r->in.in_data, &out_data,
9810                                                   r->out.needed);
9811                 break;
9812         default:
9813                 werror = WERR_INVALID_PRINT_MONITOR;
9814         }
9815
9816         if (!W_ERROR_IS_OK(werror)) {
9817                 return werror;
9818         }
9819
9820         *r->out.status_code = 0;
9821
9822         if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
9823                 memcpy(r->out.out_data, out_data.data,
9824                         MIN(r->in.out_data_size, out_data.length));
9825         }
9826
9827         return WERR_OK;
9828 }
9829
9830 /****************************************************************
9831  _spoolss_AddPrintProcessor
9832 ****************************************************************/
9833
9834 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
9835                                   struct spoolss_AddPrintProcessor *r)
9836 {
9837         /* for now, just indicate success and ignore the add.  We'll
9838            automatically set the winprint processor for printer
9839            entries later.  Used to debug the LexMark Optra S 1855 PCL
9840            driver --jerry */
9841
9842         return WERR_OK;
9843 }
9844
9845 /****************************************************************
9846  _spoolss_AddPort
9847 ****************************************************************/
9848
9849 WERROR _spoolss_AddPort(struct pipes_struct *p,
9850                         struct spoolss_AddPort *r)
9851 {
9852         /* do what w2k3 does */
9853
9854         return WERR_NOT_SUPPORTED;
9855 }
9856
9857 /****************************************************************
9858  _spoolss_GetPrinterDriver
9859 ****************************************************************/
9860
9861 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
9862                                  struct spoolss_GetPrinterDriver *r)
9863 {
9864         p->rng_fault_state = true;
9865         return WERR_NOT_SUPPORTED;
9866 }
9867
9868 /****************************************************************
9869  _spoolss_ReadPrinter
9870 ****************************************************************/
9871
9872 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
9873                             struct spoolss_ReadPrinter *r)
9874 {
9875         p->rng_fault_state = true;
9876         return WERR_NOT_SUPPORTED;
9877 }
9878
9879 /****************************************************************
9880  _spoolss_WaitForPrinterChange
9881 ****************************************************************/
9882
9883 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
9884                                      struct spoolss_WaitForPrinterChange *r)
9885 {
9886         p->rng_fault_state = true;
9887         return WERR_NOT_SUPPORTED;
9888 }
9889
9890 /****************************************************************
9891  _spoolss_ConfigurePort
9892 ****************************************************************/
9893
9894 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
9895                               struct spoolss_ConfigurePort *r)
9896 {
9897         p->rng_fault_state = true;
9898         return WERR_NOT_SUPPORTED;
9899 }
9900
9901 /****************************************************************
9902  _spoolss_DeletePort
9903 ****************************************************************/
9904
9905 WERROR _spoolss_DeletePort(struct pipes_struct *p,
9906                            struct spoolss_DeletePort *r)
9907 {
9908         p->rng_fault_state = true;
9909         return WERR_NOT_SUPPORTED;
9910 }
9911
9912 /****************************************************************
9913  _spoolss_CreatePrinterIC
9914 ****************************************************************/
9915
9916 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
9917                                 struct spoolss_CreatePrinterIC *r)
9918 {
9919         p->rng_fault_state = true;
9920         return WERR_NOT_SUPPORTED;
9921 }
9922
9923 /****************************************************************
9924  _spoolss_PlayGDIScriptOnPrinterIC
9925 ****************************************************************/
9926
9927 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
9928                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
9929 {
9930         p->rng_fault_state = true;
9931         return WERR_NOT_SUPPORTED;
9932 }
9933
9934 /****************************************************************
9935  _spoolss_DeletePrinterIC
9936 ****************************************************************/
9937
9938 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
9939                                 struct spoolss_DeletePrinterIC *r)
9940 {
9941         p->rng_fault_state = true;
9942         return WERR_NOT_SUPPORTED;
9943 }
9944
9945 /****************************************************************
9946  _spoolss_AddPrinterConnection
9947 ****************************************************************/
9948
9949 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
9950                                      struct spoolss_AddPrinterConnection *r)
9951 {
9952         p->rng_fault_state = true;
9953         return WERR_NOT_SUPPORTED;
9954 }
9955
9956 /****************************************************************
9957  _spoolss_DeletePrinterConnection
9958 ****************************************************************/
9959
9960 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
9961                                         struct spoolss_DeletePrinterConnection *r)
9962 {
9963         p->rng_fault_state = true;
9964         return WERR_NOT_SUPPORTED;
9965 }
9966
9967 /****************************************************************
9968  _spoolss_PrinterMessageBox
9969 ****************************************************************/
9970
9971 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
9972                                   struct spoolss_PrinterMessageBox *r)
9973 {
9974         p->rng_fault_state = true;
9975         return WERR_NOT_SUPPORTED;
9976 }
9977
9978 /****************************************************************
9979  _spoolss_AddMonitor
9980 ****************************************************************/
9981
9982 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
9983                            struct spoolss_AddMonitor *r)
9984 {
9985         p->rng_fault_state = true;
9986         return WERR_NOT_SUPPORTED;
9987 }
9988
9989 /****************************************************************
9990  _spoolss_DeleteMonitor
9991 ****************************************************************/
9992
9993 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
9994                               struct spoolss_DeleteMonitor *r)
9995 {
9996         p->rng_fault_state = true;
9997         return WERR_NOT_SUPPORTED;
9998 }
9999
10000 /****************************************************************
10001  _spoolss_DeletePrintProcessor
10002 ****************************************************************/
10003
10004 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10005                                      struct spoolss_DeletePrintProcessor *r)
10006 {
10007         p->rng_fault_state = true;
10008         return WERR_NOT_SUPPORTED;
10009 }
10010
10011 /****************************************************************
10012  _spoolss_AddPrintProvidor
10013 ****************************************************************/
10014
10015 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10016                                  struct spoolss_AddPrintProvidor *r)
10017 {
10018         p->rng_fault_state = true;
10019         return WERR_NOT_SUPPORTED;
10020 }
10021
10022 /****************************************************************
10023  _spoolss_DeletePrintProvidor
10024 ****************************************************************/
10025
10026 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10027                                     struct spoolss_DeletePrintProvidor *r)
10028 {
10029         p->rng_fault_state = true;
10030         return WERR_NOT_SUPPORTED;
10031 }
10032
10033 /****************************************************************
10034  _spoolss_FindFirstPrinterChangeNotification
10035 ****************************************************************/
10036
10037 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10038                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
10039 {
10040         p->rng_fault_state = true;
10041         return WERR_NOT_SUPPORTED;
10042 }
10043
10044 /****************************************************************
10045  _spoolss_FindNextPrinterChangeNotification
10046 ****************************************************************/
10047
10048 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10049                                                   struct spoolss_FindNextPrinterChangeNotification *r)
10050 {
10051         p->rng_fault_state = true;
10052         return WERR_NOT_SUPPORTED;
10053 }
10054
10055 /****************************************************************
10056  _spoolss_RouterFindFirstPrinterChangeNotificationOld
10057 ****************************************************************/
10058
10059 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10060                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10061 {
10062         p->rng_fault_state = true;
10063         return WERR_NOT_SUPPORTED;
10064 }
10065
10066 /****************************************************************
10067  _spoolss_ReplyOpenPrinter
10068 ****************************************************************/
10069
10070 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10071                                  struct spoolss_ReplyOpenPrinter *r)
10072 {
10073         p->rng_fault_state = true;
10074         return WERR_NOT_SUPPORTED;
10075 }
10076
10077 /****************************************************************
10078  _spoolss_RouterReplyPrinter
10079 ****************************************************************/
10080
10081 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10082                                    struct spoolss_RouterReplyPrinter *r)
10083 {
10084         p->rng_fault_state = true;
10085         return WERR_NOT_SUPPORTED;
10086 }
10087
10088 /****************************************************************
10089  _spoolss_ReplyClosePrinter
10090 ****************************************************************/
10091
10092 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10093                                   struct spoolss_ReplyClosePrinter *r)
10094 {
10095         p->rng_fault_state = true;
10096         return WERR_NOT_SUPPORTED;
10097 }
10098
10099 /****************************************************************
10100  _spoolss_AddPortEx
10101 ****************************************************************/
10102
10103 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10104                           struct spoolss_AddPortEx *r)
10105 {
10106         p->rng_fault_state = true;
10107         return WERR_NOT_SUPPORTED;
10108 }
10109
10110 /****************************************************************
10111  _spoolss_RouterFindFirstPrinterChangeNotification
10112 ****************************************************************/
10113
10114 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10115                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10116 {
10117         p->rng_fault_state = true;
10118         return WERR_NOT_SUPPORTED;
10119 }
10120
10121 /****************************************************************
10122  _spoolss_SpoolerInit
10123 ****************************************************************/
10124
10125 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10126                             struct spoolss_SpoolerInit *r)
10127 {
10128         p->rng_fault_state = true;
10129         return WERR_NOT_SUPPORTED;
10130 }
10131
10132 /****************************************************************
10133  _spoolss_ResetPrinterEx
10134 ****************************************************************/
10135
10136 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10137                                struct spoolss_ResetPrinterEx *r)
10138 {
10139         p->rng_fault_state = true;
10140         return WERR_NOT_SUPPORTED;
10141 }
10142
10143 /****************************************************************
10144  _spoolss_RouterReplyPrinterEx
10145 ****************************************************************/
10146
10147 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10148                                      struct spoolss_RouterReplyPrinterEx *r)
10149 {
10150         p->rng_fault_state = true;
10151         return WERR_NOT_SUPPORTED;
10152 }
10153
10154 /****************************************************************
10155  _spoolss_44
10156 ****************************************************************/
10157
10158 WERROR _spoolss_44(struct pipes_struct *p,
10159                    struct spoolss_44 *r)
10160 {
10161         p->rng_fault_state = true;
10162         return WERR_NOT_SUPPORTED;
10163 }
10164
10165 /****************************************************************
10166  _spoolss_47
10167 ****************************************************************/
10168
10169 WERROR _spoolss_47(struct pipes_struct *p,
10170                    struct spoolss_47 *r)
10171 {
10172         p->rng_fault_state = true;
10173         return WERR_NOT_SUPPORTED;
10174 }
10175
10176 /****************************************************************
10177  _spoolss_4a
10178 ****************************************************************/
10179
10180 WERROR _spoolss_4a(struct pipes_struct *p,
10181                    struct spoolss_4a *r)
10182 {
10183         p->rng_fault_state = true;
10184         return WERR_NOT_SUPPORTED;
10185 }
10186
10187 /****************************************************************
10188  _spoolss_4b
10189 ****************************************************************/
10190
10191 WERROR _spoolss_4b(struct pipes_struct *p,
10192                    struct spoolss_4b *r)
10193 {
10194         p->rng_fault_state = true;
10195         return WERR_NOT_SUPPORTED;
10196 }
10197
10198 /****************************************************************
10199  _spoolss_4c
10200 ****************************************************************/
10201
10202 WERROR _spoolss_4c(struct pipes_struct *p,
10203                    struct spoolss_4c *r)
10204 {
10205         p->rng_fault_state = true;
10206         return WERR_NOT_SUPPORTED;
10207 }
10208
10209 /****************************************************************
10210  _spoolss_53
10211 ****************************************************************/
10212
10213 WERROR _spoolss_53(struct pipes_struct *p,
10214                    struct spoolss_53 *r)
10215 {
10216         p->rng_fault_state = true;
10217         return WERR_NOT_SUPPORTED;
10218 }
10219
10220 /****************************************************************
10221  _spoolss_55
10222 ****************************************************************/
10223
10224 WERROR _spoolss_55(struct pipes_struct *p,
10225                    struct spoolss_55 *r)
10226 {
10227         p->rng_fault_state = true;
10228         return WERR_NOT_SUPPORTED;
10229 }
10230
10231 /****************************************************************
10232  _spoolss_56
10233 ****************************************************************/
10234
10235 WERROR _spoolss_56(struct pipes_struct *p,
10236                    struct spoolss_56 *r)
10237 {
10238         p->rng_fault_state = true;
10239         return WERR_NOT_SUPPORTED;
10240 }
10241
10242 /****************************************************************
10243  _spoolss_57
10244 ****************************************************************/
10245
10246 WERROR _spoolss_57(struct pipes_struct *p,
10247                    struct spoolss_57 *r)
10248 {
10249         p->rng_fault_state = true;
10250         return WERR_NOT_SUPPORTED;
10251 }
10252
10253 /****************************************************************
10254  _spoolss_5a
10255 ****************************************************************/
10256
10257 WERROR _spoolss_5a(struct pipes_struct *p,
10258                    struct spoolss_5a *r)
10259 {
10260         p->rng_fault_state = true;
10261         return WERR_NOT_SUPPORTED;
10262 }
10263
10264 /****************************************************************
10265  _spoolss_5b
10266 ****************************************************************/
10267
10268 WERROR _spoolss_5b(struct pipes_struct *p,
10269                    struct spoolss_5b *r)
10270 {
10271         p->rng_fault_state = true;
10272         return WERR_NOT_SUPPORTED;
10273 }
10274
10275 /****************************************************************
10276  _spoolss_5c
10277 ****************************************************************/
10278
10279 WERROR _spoolss_5c(struct pipes_struct *p,
10280                    struct spoolss_5c *r)
10281 {
10282         p->rng_fault_state = true;
10283         return WERR_NOT_SUPPORTED;
10284 }
10285
10286 /****************************************************************
10287  _spoolss_5d
10288 ****************************************************************/
10289
10290 WERROR _spoolss_5d(struct pipes_struct *p,
10291                    struct spoolss_5d *r)
10292 {
10293         p->rng_fault_state = true;
10294         return WERR_NOT_SUPPORTED;
10295 }
10296
10297 /****************************************************************
10298  _spoolss_5e
10299 ****************************************************************/
10300
10301 WERROR _spoolss_5e(struct pipes_struct *p,
10302                    struct spoolss_5e *r)
10303 {
10304         p->rng_fault_state = true;
10305         return WERR_NOT_SUPPORTED;
10306 }
10307
10308 /****************************************************************
10309  _spoolss_5f
10310 ****************************************************************/
10311
10312 WERROR _spoolss_5f(struct pipes_struct *p,
10313                    struct spoolss_5f *r)
10314 {
10315         p->rng_fault_state = true;
10316         return WERR_NOT_SUPPORTED;
10317 }
10318
10319 /****************************************************************
10320  _spoolss_60
10321 ****************************************************************/
10322
10323 WERROR _spoolss_60(struct pipes_struct *p,
10324                    struct spoolss_60 *r)
10325 {
10326         p->rng_fault_state = true;
10327         return WERR_NOT_SUPPORTED;
10328 }
10329
10330 /****************************************************************
10331  _spoolss_61
10332 ****************************************************************/
10333
10334 WERROR _spoolss_61(struct pipes_struct *p,
10335                    struct spoolss_61 *r)
10336 {
10337         p->rng_fault_state = true;
10338         return WERR_NOT_SUPPORTED;
10339 }
10340
10341 /****************************************************************
10342  _spoolss_62
10343 ****************************************************************/
10344
10345 WERROR _spoolss_62(struct pipes_struct *p,
10346                    struct spoolss_62 *r)
10347 {
10348         p->rng_fault_state = true;
10349         return WERR_NOT_SUPPORTED;
10350 }
10351
10352 /****************************************************************
10353  _spoolss_63
10354 ****************************************************************/
10355
10356 WERROR _spoolss_63(struct pipes_struct *p,
10357                    struct spoolss_63 *r)
10358 {
10359         p->rng_fault_state = true;
10360         return WERR_NOT_SUPPORTED;
10361 }
10362
10363 /****************************************************************
10364  _spoolss_64
10365 ****************************************************************/
10366
10367 WERROR _spoolss_64(struct pipes_struct *p,
10368                    struct spoolss_64 *r)
10369 {
10370         p->rng_fault_state = true;
10371         return WERR_NOT_SUPPORTED;
10372 }
10373
10374 /****************************************************************
10375  _spoolss_65
10376 ****************************************************************/
10377
10378 WERROR _spoolss_65(struct pipes_struct *p,
10379                    struct spoolss_65 *r)
10380 {
10381         p->rng_fault_state = true;
10382         return WERR_NOT_SUPPORTED;
10383 }
10384
10385 /****************************************************************
10386  _spoolss_GetCorePrinterDrivers
10387 ****************************************************************/
10388
10389 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
10390                                       struct spoolss_GetCorePrinterDrivers *r)
10391 {
10392         p->rng_fault_state = true;
10393         return WERR_NOT_SUPPORTED;
10394 }
10395
10396 /****************************************************************
10397  _spoolss_67
10398 ****************************************************************/
10399
10400 WERROR _spoolss_67(struct pipes_struct *p,
10401                    struct spoolss_67 *r)
10402 {
10403         p->rng_fault_state = true;
10404         return WERR_NOT_SUPPORTED;
10405 }
10406
10407 /****************************************************************
10408  _spoolss_GetPrinterDriverPackagePath
10409 ****************************************************************/
10410
10411 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
10412                                             struct spoolss_GetPrinterDriverPackagePath *r)
10413 {
10414         p->rng_fault_state = true;
10415         return WERR_NOT_SUPPORTED;
10416 }
10417
10418 /****************************************************************
10419  _spoolss_69
10420 ****************************************************************/
10421
10422 WERROR _spoolss_69(struct pipes_struct *p,
10423                    struct spoolss_69 *r)
10424 {
10425         p->rng_fault_state = true;
10426         return WERR_NOT_SUPPORTED;
10427 }
10428
10429 /****************************************************************
10430  _spoolss_6a
10431 ****************************************************************/
10432
10433 WERROR _spoolss_6a(struct pipes_struct *p,
10434                    struct spoolss_6a *r)
10435 {
10436         p->rng_fault_state = true;
10437         return WERR_NOT_SUPPORTED;
10438 }
10439
10440 /****************************************************************
10441  _spoolss_6b
10442 ****************************************************************/
10443
10444 WERROR _spoolss_6b(struct pipes_struct *p,
10445                    struct spoolss_6b *r)
10446 {
10447         p->rng_fault_state = true;
10448         return WERR_NOT_SUPPORTED;
10449 }
10450
10451 /****************************************************************
10452  _spoolss_6c
10453 ****************************************************************/
10454
10455 WERROR _spoolss_6c(struct pipes_struct *p,
10456                    struct spoolss_6c *r)
10457 {
10458         p->rng_fault_state = true;
10459         return WERR_NOT_SUPPORTED;
10460 }
10461
10462 /****************************************************************
10463  _spoolss_6d
10464 ****************************************************************/
10465
10466 WERROR _spoolss_6d(struct pipes_struct *p,
10467                    struct spoolss_6d *r)
10468 {
10469         p->rng_fault_state = true;
10470         return WERR_NOT_SUPPORTED;
10471 }