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