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