s3-privs Further changes to remove SE_PRIV
[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         uint64_t 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                         uint64_t 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         uint64_t                         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         uint64_t                         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                 goto out;
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  out:
4588         if (!W_ERROR_IS_OK(result)) {
4589                 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4590                           r->in.level, win_errstr(result)));
4591                 TALLOC_FREE(r->out.info);
4592                 return result;
4593         }
4594
4595         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo, 
4596                                                r->out.info, r->in.level);
4597         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4598
4599         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4600 }
4601
4602 /********************************************************************
4603  ********************************************************************/
4604
4605 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4606         do { \
4607                 if (in && strlen(in)) { \
4608                         out = talloc_strdup(mem_ctx, in); \
4609                 } else { \
4610                         out = talloc_strdup(mem_ctx, ""); \
4611                 } \
4612                 W_ERROR_HAVE_NO_MEMORY(out); \
4613         } while (0);
4614
4615 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4616         do { \
4617                 if (in && strlen(in)) { \
4618                         out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4619                 } else { \
4620                         out = talloc_strdup(mem_ctx, ""); \
4621                 } \
4622                 W_ERROR_HAVE_NO_MEMORY(out); \
4623         } while (0);
4624
4625 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4626                                                   const char **string_array,
4627                                                   const char ***presult,
4628                                                   const char *cservername,
4629                                                   const char *arch,
4630                                                   int version)
4631 {
4632         int i, num_strings = 0;
4633         const char **array = NULL;
4634
4635         if (string_array == NULL) {
4636                 return WERR_INVALID_PARAMETER;;
4637         }
4638
4639         for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4640                 const char *str = NULL;
4641
4642                 if (cservername == NULL || arch == NULL) {
4643                         FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4644                 } else {
4645                         FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4646                 }
4647
4648                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4649                         TALLOC_FREE(array);
4650                         return WERR_NOMEM;
4651                 }
4652         }
4653
4654         if (i > 0) {
4655                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4656                              &array, &num_strings);
4657         }
4658
4659         if (presult) {
4660                 *presult = array;
4661         }
4662
4663         return WERR_OK;
4664 }
4665
4666 /********************************************************************
4667  * fill a spoolss_DriverInfo1 struct
4668  ********************************************************************/
4669
4670 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4671                                         struct spoolss_DriverInfo1 *r,
4672                                         const struct spoolss_DriverInfo8 *driver,
4673                                         const char *servername)
4674 {
4675         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4676         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4677
4678         return WERR_OK;
4679 }
4680
4681 /********************************************************************
4682  * fill a spoolss_DriverInfo2 struct
4683  ********************************************************************/
4684
4685 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4686                                         struct spoolss_DriverInfo2 *r,
4687                                         const struct spoolss_DriverInfo8 *driver,
4688                                         const char *servername)
4689
4690 {
4691         const char *cservername = canon_servername(servername);
4692
4693         r->version              = driver->version;
4694
4695         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4696         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4697         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4698         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4699
4700         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4701                                driver->architecture,
4702                                driver->version,
4703                                driver->driver_path,
4704                                r->driver_path);
4705
4706         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4707                                driver->architecture,
4708                                driver->version,
4709                                driver->data_file,
4710                                r->data_file);
4711
4712         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4713                                driver->architecture,
4714                                driver->version,
4715                                driver->config_file,
4716                                r->config_file);
4717
4718         return WERR_OK;
4719 }
4720
4721 /********************************************************************
4722  * fill a spoolss_DriverInfo3 struct
4723  ********************************************************************/
4724
4725 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4726                                         struct spoolss_DriverInfo3 *r,
4727                                         const struct spoolss_DriverInfo8 *driver,
4728                                         const char *servername)
4729 {
4730         const char *cservername = canon_servername(servername);
4731
4732         r->version              = driver->version;
4733
4734         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4735         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4736         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4737         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4738
4739         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4740                                driver->architecture,
4741                                driver->version,
4742                                driver->driver_path,
4743                                r->driver_path);
4744
4745         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4746                                driver->architecture,
4747                                driver->version,
4748                                driver->data_file,
4749                                r->data_file);
4750
4751         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4752                                driver->architecture,
4753                                driver->version,
4754                                driver->config_file,
4755                                r->config_file);
4756
4757         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4758                                driver->architecture,
4759                                driver->version,
4760                                driver->help_file,
4761                                r->help_file);
4762
4763         FILL_DRIVER_STRING(mem_ctx,
4764                            driver->monitor_name,
4765                            r->monitor_name);
4766
4767         FILL_DRIVER_STRING(mem_ctx,
4768                            driver->default_datatype,
4769                            r->default_datatype);
4770
4771         return string_array_from_driver_info(mem_ctx,
4772                                              driver->dependent_files,
4773                                              &r->dependent_files,
4774                                              cservername,
4775                                              driver->architecture,
4776                                              driver->version);
4777 }
4778
4779 /********************************************************************
4780  * fill a spoolss_DriverInfo4 struct
4781  ********************************************************************/
4782
4783 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4784                                         struct spoolss_DriverInfo4 *r,
4785                                         const struct spoolss_DriverInfo8 *driver,
4786                                         const char *servername)
4787 {
4788         const char *cservername = canon_servername(servername);
4789         WERROR result;
4790
4791         r->version              = driver->version;
4792
4793         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4794         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4795         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4796         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4797
4798         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4799                                driver->architecture,
4800                                driver->version,
4801                                driver->driver_path,
4802                                r->driver_path);
4803
4804         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4805                                driver->architecture,
4806                                driver->version,
4807                                driver->data_file,
4808                                r->data_file);
4809
4810         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4811                                driver->architecture,
4812                                driver->version,
4813                                driver->config_file,
4814                                r->config_file);
4815
4816         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4817                                driver->architecture,
4818                                driver->version,
4819                                driver->help_file,
4820                                r->help_file);
4821
4822         result = string_array_from_driver_info(mem_ctx,
4823                                                driver->dependent_files,
4824                                                &r->dependent_files,
4825                                                cservername,
4826                                                driver->architecture,
4827                                                driver->version);
4828         if (!W_ERROR_IS_OK(result)) {
4829                 return result;
4830         }
4831
4832         FILL_DRIVER_STRING(mem_ctx,
4833                            driver->monitor_name,
4834                            r->monitor_name);
4835
4836         FILL_DRIVER_STRING(mem_ctx,
4837                            driver->default_datatype,
4838                            r->default_datatype);
4839
4840
4841         result = string_array_from_driver_info(mem_ctx,
4842                                                driver->previous_names,
4843                                                &r->previous_names,
4844                                                NULL, NULL, 0);
4845
4846         return result;
4847 }
4848
4849 /********************************************************************
4850  * fill a spoolss_DriverInfo5 struct
4851  ********************************************************************/
4852
4853 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
4854                                         struct spoolss_DriverInfo5 *r,
4855                                         const struct spoolss_DriverInfo8 *driver,
4856                                         const char *servername)
4857 {
4858         const char *cservername = canon_servername(servername);
4859
4860         r->version              = driver->version;
4861
4862         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4863         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4864         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4865         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4866
4867         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4868                                driver->architecture,
4869                                driver->version,
4870                                driver->driver_path,
4871                                r->driver_path);
4872
4873         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4874                                driver->architecture,
4875                                driver->version,
4876                                driver->data_file,
4877                                r->data_file);
4878
4879         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4880                                driver->architecture,
4881                                driver->version,
4882                                driver->config_file,
4883                                r->config_file);
4884
4885         r->driver_attributes    = 0;
4886         r->config_version       = 0;
4887         r->driver_version       = 0;
4888
4889         return WERR_OK;
4890 }
4891 /********************************************************************
4892  * fill a spoolss_DriverInfo6 struct
4893  ********************************************************************/
4894
4895 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
4896                                         struct spoolss_DriverInfo6 *r,
4897                                         const struct spoolss_DriverInfo8 *driver,
4898                                         const char *servername)
4899 {
4900         const char *cservername = canon_servername(servername);
4901         WERROR result;
4902
4903         r->version              = driver->version;
4904
4905         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4906         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4907         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4908         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4909
4910         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4911                                driver->architecture,
4912                                driver->version,
4913                                driver->driver_path,
4914                                r->driver_path);
4915
4916         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4917                                driver->architecture,
4918                                driver->version,
4919                                driver->data_file,
4920                                r->data_file);
4921
4922         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4923                                driver->architecture,
4924                                driver->version,
4925                                driver->config_file,
4926                                r->config_file);
4927
4928         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4929                                driver->architecture,
4930                                driver->version,
4931                                driver->help_file,
4932                                r->help_file);
4933
4934         FILL_DRIVER_STRING(mem_ctx,
4935                            driver->monitor_name,
4936                            r->monitor_name);
4937
4938         FILL_DRIVER_STRING(mem_ctx,
4939                            driver->default_datatype,
4940                            r->default_datatype);
4941
4942         result = string_array_from_driver_info(mem_ctx,
4943                                                driver->dependent_files,
4944                                                &r->dependent_files,
4945                                                cservername,
4946                                                driver->architecture,
4947                                                driver->version);
4948         if (!W_ERROR_IS_OK(result)) {
4949                 return result;
4950         }
4951
4952         result = string_array_from_driver_info(mem_ctx,
4953                                                driver->previous_names,
4954                                                &r->previous_names,
4955                                                NULL, NULL, 0);
4956         if (!W_ERROR_IS_OK(result)) {
4957                 return result;
4958         }
4959
4960         r->driver_date          = driver->driver_date;
4961         r->driver_version       = driver->driver_version;
4962
4963         FILL_DRIVER_STRING(mem_ctx,
4964                            driver->manufacturer_name,
4965                            r->manufacturer_name);
4966         FILL_DRIVER_STRING(mem_ctx,
4967                            driver->manufacturer_url,
4968                            r->manufacturer_url);
4969         FILL_DRIVER_STRING(mem_ctx,
4970                            driver->hardware_id,
4971                            r->hardware_id);
4972         FILL_DRIVER_STRING(mem_ctx,
4973                            driver->provider,
4974                            r->provider);
4975
4976         return WERR_OK;
4977 }
4978
4979 /********************************************************************
4980  * fill a spoolss_DriverInfo8 struct
4981  ********************************************************************/
4982
4983 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
4984                                         struct spoolss_DriverInfo8 *r,
4985                                         const struct spoolss_DriverInfo8 *driver,
4986                                         const char *servername)
4987 {
4988         const char *cservername = canon_servername(servername);
4989         WERROR result;
4990
4991         r->version              = driver->version;
4992
4993         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4994         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4995         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4996         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4997
4998         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4999                                driver->architecture,
5000                                driver->version,
5001                                driver->driver_path,
5002                                r->driver_path);
5003
5004         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5005                                driver->architecture,
5006                                driver->version,
5007                                driver->data_file,
5008                                r->data_file);
5009
5010         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5011                                driver->architecture,
5012                                driver->version,
5013                                driver->config_file,
5014                                r->config_file);
5015
5016         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5017                                driver->architecture,
5018                                driver->version,
5019                                driver->help_file,
5020                                r->help_file);
5021
5022         FILL_DRIVER_STRING(mem_ctx,
5023                            driver->monitor_name,
5024                            r->monitor_name);
5025
5026         FILL_DRIVER_STRING(mem_ctx,
5027                            driver->default_datatype,
5028                            r->default_datatype);
5029
5030         result = string_array_from_driver_info(mem_ctx,
5031                                                driver->dependent_files,
5032                                                &r->dependent_files,
5033                                                cservername,
5034                                                driver->architecture,
5035                                                driver->version);
5036         if (!W_ERROR_IS_OK(result)) {
5037                 return result;
5038         }
5039
5040         result = string_array_from_driver_info(mem_ctx,
5041                                                driver->previous_names,
5042                                                &r->previous_names,
5043                                                NULL, NULL, 0);
5044         if (!W_ERROR_IS_OK(result)) {
5045                 return result;
5046         }
5047
5048         r->driver_date          = driver->driver_date;
5049         r->driver_version       = driver->driver_version;
5050
5051         FILL_DRIVER_STRING(mem_ctx,
5052                            driver->manufacturer_name,
5053                            r->manufacturer_name);
5054         FILL_DRIVER_STRING(mem_ctx,
5055                            driver->manufacturer_url,
5056                            r->manufacturer_url);
5057         FILL_DRIVER_STRING(mem_ctx,
5058                            driver->hardware_id,
5059                            r->hardware_id);
5060         FILL_DRIVER_STRING(mem_ctx,
5061                            driver->provider,
5062                            r->provider);
5063
5064         FILL_DRIVER_STRING(mem_ctx,
5065                            driver->print_processor,
5066                            r->print_processor);
5067         FILL_DRIVER_STRING(mem_ctx,
5068                            driver->vendor_setup,
5069                            r->vendor_setup);
5070
5071         result = string_array_from_driver_info(mem_ctx,
5072                                                driver->color_profiles,
5073                                                &r->color_profiles,
5074                                                NULL, NULL, 0);
5075         if (!W_ERROR_IS_OK(result)) {
5076                 return result;
5077         }
5078
5079         FILL_DRIVER_STRING(mem_ctx,
5080                            driver->inf_path,
5081                            r->inf_path);
5082
5083         r->printer_driver_attributes    = driver->printer_driver_attributes;
5084
5085         result = string_array_from_driver_info(mem_ctx,
5086                                                driver->core_driver_dependencies,
5087                                                &r->core_driver_dependencies,
5088                                                NULL, NULL, 0);
5089         if (!W_ERROR_IS_OK(result)) {
5090                 return result;
5091         }
5092
5093         r->min_inbox_driver_ver_date    = driver->min_inbox_driver_ver_date;
5094         r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5095
5096         return WERR_OK;
5097 }
5098
5099 #if 0 /* disabled until marshalling issues are resolved - gd */
5100 /********************************************************************
5101  ********************************************************************/
5102
5103 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5104                                           struct spoolss_DriverFileInfo *r,
5105                                           const char *cservername,
5106                                           const char *file_name,
5107                                           enum spoolss_DriverFileType file_type,
5108                                           uint32_t file_version)
5109 {
5110         r->file_name    = talloc_asprintf(mem_ctx, "\\\\%s%s",
5111                                           cservername, file_name);
5112         W_ERROR_HAVE_NO_MEMORY(r->file_name);
5113         r->file_type    = file_type;
5114         r->file_version = file_version;
5115
5116         return WERR_OK;
5117 }
5118
5119 /********************************************************************
5120  ********************************************************************/
5121
5122 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5123                                                  const struct spoolss_DriverInfo8 *driver,
5124                                                  const char *cservername,
5125                                                  struct spoolss_DriverFileInfo **info_p,
5126                                                  uint32_t *count_p)
5127 {
5128         struct spoolss_DriverFileInfo *info = NULL;
5129         uint32_t count = 0;
5130         WERROR result;
5131         uint32_t i;
5132
5133         *info_p = NULL;
5134         *count_p = 0;
5135
5136         if (strlen(driver->driver_path)) {
5137                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5138                                             struct spoolss_DriverFileInfo,
5139                                             count + 1);
5140                 W_ERROR_HAVE_NO_MEMORY(info);
5141                 result = fill_spoolss_DriverFileInfo(info,
5142                                                      &info[count],
5143                                                      cservername,
5144                                                      driver->driver_path,
5145                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5146                                                      0);
5147                 W_ERROR_NOT_OK_RETURN(result);
5148                 count++;
5149         }
5150
5151         if (strlen(driver->config_file)) {
5152                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5153                                             struct spoolss_DriverFileInfo,
5154                                             count + 1);
5155                 W_ERROR_HAVE_NO_MEMORY(info);
5156                 result = fill_spoolss_DriverFileInfo(info,
5157                                                      &info[count],
5158                                                      cservername,
5159                                                      driver->config_file,
5160                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5161                                                      0);
5162                 W_ERROR_NOT_OK_RETURN(result);
5163                 count++;
5164         }
5165
5166         if (strlen(driver->data_file)) {
5167                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5168                                             struct spoolss_DriverFileInfo,
5169                                             count + 1);
5170                 W_ERROR_HAVE_NO_MEMORY(info);
5171                 result = fill_spoolss_DriverFileInfo(info,
5172                                                      &info[count],
5173                                                      cservername,
5174                                                      driver->data_file,
5175                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
5176                                                      0);
5177                 W_ERROR_NOT_OK_RETURN(result);
5178                 count++;
5179         }
5180
5181         if (strlen(driver->help_file)) {
5182                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5183                                             struct spoolss_DriverFileInfo,
5184                                             count + 1);
5185                 W_ERROR_HAVE_NO_MEMORY(info);
5186                 result = fill_spoolss_DriverFileInfo(info,
5187                                                      &info[count],
5188                                                      cservername,
5189                                                      driver->help_file,
5190                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
5191                                                      0);
5192                 W_ERROR_NOT_OK_RETURN(result);
5193                 count++;
5194         }
5195
5196         for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5197                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5198                                             struct spoolss_DriverFileInfo,
5199                                             count + 1);
5200                 W_ERROR_HAVE_NO_MEMORY(info);
5201                 result = fill_spoolss_DriverFileInfo(info,
5202                                                      &info[count],
5203                                                      cservername,
5204                                                      driver->dependent_files[i],
5205                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5206                                                      0);
5207                 W_ERROR_NOT_OK_RETURN(result);
5208                 count++;
5209         }
5210
5211         *info_p = info;
5212         *count_p = count;
5213
5214         return WERR_OK;
5215 }
5216
5217 /********************************************************************
5218  * fill a spoolss_DriverInfo101 struct
5219  ********************************************************************/
5220
5221 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5222                                           struct spoolss_DriverInfo101 *r,
5223                                           const struct spoolss_DriverInfo8 *driver,
5224                                           const char *servername)
5225 {
5226         const char *cservername = canon_servername(servername);
5227         WERROR result;
5228
5229         r->version              = driver->version;
5230
5231         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5232         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5233         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5234         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5235
5236         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5237                                                     cservername,
5238                                                     &r->file_info,
5239                                                     &r->file_count);
5240         if (!W_ERROR_IS_OK(result)) {
5241                 return result;
5242         }
5243
5244         FILL_DRIVER_STRING(mem_ctx,
5245                            driver->monitor_name,
5246                            r->monitor_name);
5247
5248         FILL_DRIVER_STRING(mem_ctx,
5249                            driver->default_datatype,
5250                            r->default_datatype);
5251
5252         result = string_array_from_driver_info(mem_ctx,
5253                                                driver->previous_names,
5254                                                &r->previous_names,
5255                                                NULL, NULL, 0);
5256         if (!W_ERROR_IS_OK(result)) {
5257                 return result;
5258         }
5259
5260         r->driver_date          = driver->driver_date;
5261         r->driver_version       = driver->driver_version;
5262
5263         FILL_DRIVER_STRING(mem_ctx,
5264                            driver->manufacturer_name,
5265                            r->manufacturer_name);
5266         FILL_DRIVER_STRING(mem_ctx,
5267                            driver->manufacturer_url,
5268                            r->manufacturer_url);
5269         FILL_DRIVER_STRING(mem_ctx,
5270                            driver->hardware_id,
5271                            r->hardware_id);
5272         FILL_DRIVER_STRING(mem_ctx,
5273                            driver->provider,
5274                            r->provider);
5275
5276         return WERR_OK;
5277 }
5278 #endif
5279 /********************************************************************
5280  ********************************************************************/
5281
5282 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5283                                                   const struct auth_serversupplied_info *server_info,
5284                                                   struct messaging_context *msg_ctx,
5285                                                   uint32_t level,
5286                                                   union spoolss_DriverInfo *r,
5287                                                   int snum,
5288                                                   const char *servername,
5289                                                   const char *architecture,
5290                                                   uint32_t version)
5291 {
5292         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5293         struct spoolss_DriverInfo8 *driver;
5294         WERROR result;
5295
5296         result = winreg_get_printer(mem_ctx,
5297                                     server_info,
5298                                     msg_ctx,
5299                                     servername,
5300                                     lp_const_servicename(snum),
5301                                     &pinfo2);
5302
5303         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5304                 win_errstr(result)));
5305
5306         if (!W_ERROR_IS_OK(result)) {
5307                 return WERR_INVALID_PRINTER_NAME;
5308         }
5309
5310         result = winreg_get_driver(mem_ctx, server_info, msg_ctx,
5311                                    architecture,
5312                                    pinfo2->drivername, version, &driver);
5313
5314         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5315                 win_errstr(result)));
5316
5317         if (!W_ERROR_IS_OK(result)) {
5318                 /*
5319                  * Is this a W2k client ?
5320                  */
5321
5322                 if (version < 3) {
5323                         talloc_free(pinfo2);
5324                         return WERR_UNKNOWN_PRINTER_DRIVER;
5325                 }
5326
5327                 /* Yes - try again with a WinNT driver. */
5328                 version = 2;
5329                 result = winreg_get_driver(mem_ctx, server_info, msg_ctx,
5330                                            architecture,
5331                                            pinfo2->drivername,
5332                                            version, &driver);
5333                 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5334                         win_errstr(result)));
5335                 if (!W_ERROR_IS_OK(result)) {
5336                         talloc_free(pinfo2);
5337                         return WERR_UNKNOWN_PRINTER_DRIVER;
5338                 }
5339         }
5340
5341         switch (level) {
5342         case 1:
5343                 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5344                 break;
5345         case 2:
5346                 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5347                 break;
5348         case 3:
5349                 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5350                 break;
5351         case 4:
5352                 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5353                 break;
5354         case 5:
5355                 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5356                 break;
5357         case 6:
5358                 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5359                 break;
5360         case 8:
5361                 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5362                 break;
5363 #if 0 /* disabled until marshalling issues are resolved - gd */
5364         case 101:
5365                 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5366                 break;
5367 #endif
5368         default:
5369                 result = WERR_UNKNOWN_LEVEL;
5370                 break;
5371         }
5372
5373         talloc_free(pinfo2);
5374         talloc_free(driver);
5375
5376         return result;
5377 }
5378
5379 /****************************************************************
5380  _spoolss_GetPrinterDriver2
5381 ****************************************************************/
5382
5383 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5384                                   struct spoolss_GetPrinterDriver2 *r)
5385 {
5386         struct printer_handle *printer;
5387         WERROR result;
5388
5389         int snum;
5390
5391         /* that's an [in out] buffer */
5392
5393         if (!r->in.buffer && (r->in.offered != 0)) {
5394                 return WERR_INVALID_PARAM;
5395         }
5396
5397         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5398
5399         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5400                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5401                 return WERR_INVALID_PRINTER_NAME;
5402         }
5403
5404         *r->out.needed = 0;
5405         *r->out.server_major_version = 0;
5406         *r->out.server_minor_version = 0;
5407
5408         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5409                 return WERR_BADFID;
5410         }
5411
5412         result = construct_printer_driver_info_level(p->mem_ctx,
5413                                                      get_server_info_system(),
5414                                                      p->msg_ctx,
5415                                                      r->in.level, r->out.info,
5416                                                      snum, printer->servername,
5417                                                      r->in.architecture,
5418                                                      r->in.client_major_version);
5419         if (!W_ERROR_IS_OK(result)) {
5420                 TALLOC_FREE(r->out.info);
5421                 return result;
5422         }
5423
5424         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo, 
5425                                                r->out.info, r->in.level);
5426         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5427
5428         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5429 }
5430
5431
5432 /****************************************************************
5433  _spoolss_StartPagePrinter
5434 ****************************************************************/
5435
5436 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5437                                  struct spoolss_StartPagePrinter *r)
5438 {
5439         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5440
5441         if (!Printer) {
5442                 DEBUG(3,("_spoolss_StartPagePrinter: "
5443                         "Error in startpageprinter printer handle\n"));
5444                 return WERR_BADFID;
5445         }
5446
5447         Printer->page_started = true;
5448         return WERR_OK;
5449 }
5450
5451 /****************************************************************
5452  _spoolss_EndPagePrinter
5453 ****************************************************************/
5454
5455 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5456                                struct spoolss_EndPagePrinter *r)
5457 {
5458         int snum;
5459
5460         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5461
5462         if (!Printer) {
5463                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5464                         OUR_HANDLE(r->in.handle)));
5465                 return WERR_BADFID;
5466         }
5467
5468         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5469                 return WERR_BADFID;
5470
5471         Printer->page_started = false;
5472         print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5473
5474         return WERR_OK;
5475 }
5476
5477 /****************************************************************
5478  _spoolss_StartDocPrinter
5479 ****************************************************************/
5480
5481 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5482                                 struct spoolss_StartDocPrinter *r)
5483 {
5484         struct spoolss_DocumentInfo1 *info_1;
5485         int snum;
5486         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5487         WERROR werr;
5488
5489         if (!Printer) {
5490                 DEBUG(2,("_spoolss_StartDocPrinter: "
5491                         "Invalid handle (%s:%u:%u)\n",
5492                         OUR_HANDLE(r->in.handle)));
5493                 return WERR_BADFID;
5494         }
5495
5496         if (Printer->jobid) {
5497                 DEBUG(2, ("_spoolss_StartDocPrinter: "
5498                           "StartDocPrinter called twice! "
5499                           "(existing jobid = %d)\n", Printer->jobid));
5500                 return WERR_INVALID_HANDLE;
5501         }
5502
5503         if (r->in.level != 1) {
5504                 return WERR_UNKNOWN_LEVEL;
5505         }
5506
5507         info_1 = r->in.info.info1;
5508
5509         /*
5510          * a nice thing with NT is it doesn't listen to what you tell it.
5511          * when asked to send _only_ RAW datas, it tries to send datas
5512          * in EMF format.
5513          *
5514          * So I add checks like in NT Server ...
5515          */
5516
5517         if (info_1->datatype) {
5518                 if (strcmp(info_1->datatype, "RAW") != 0) {
5519                         *r->out.job_id = 0;
5520                         return WERR_INVALID_DATATYPE;
5521                 }
5522         }
5523
5524         /* get the share number of the printer */
5525         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5526                 return WERR_BADFID;
5527         }
5528
5529         werr = print_job_start(get_server_info_system(),
5530                                p->msg_ctx,
5531                                p->client_id->name,
5532                                snum,
5533                                info_1->document_name,
5534                                info_1->output_file,
5535                                Printer->devmode,
5536                                &Printer->jobid);
5537
5538         /* An error occured in print_job_start() so return an appropriate
5539            NT error code. */
5540
5541         if (!W_ERROR_IS_OK(werr)) {
5542                 return werr;
5543         }
5544
5545         Printer->document_started = true;
5546         *r->out.job_id = Printer->jobid;
5547
5548         return WERR_OK;
5549 }
5550
5551 /****************************************************************
5552  _spoolss_EndDocPrinter
5553 ****************************************************************/
5554
5555 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5556                               struct spoolss_EndDocPrinter *r)
5557 {
5558         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5559         NTSTATUS status;
5560         int snum;
5561
5562         if (!Printer) {
5563                 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5564                         OUR_HANDLE(r->in.handle)));
5565                 return WERR_BADFID;
5566         }
5567
5568         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5569                 return WERR_BADFID;
5570         }
5571
5572         Printer->document_started = false;
5573         status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5574         if (!NT_STATUS_IS_OK(status)) {
5575                 DEBUG(2, ("_spoolss_EndDocPrinter: "
5576                           "print_job_end failed [%s]\n",
5577                           nt_errstr(status)));
5578         }
5579
5580         Printer->jobid = 0;
5581         return ntstatus_to_werror(status);
5582 }
5583
5584 /****************************************************************
5585  _spoolss_WritePrinter
5586 ****************************************************************/
5587
5588 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5589                              struct spoolss_WritePrinter *r)
5590 {
5591         ssize_t buffer_written;
5592         int snum;
5593         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5594
5595         if (!Printer) {
5596                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5597                         OUR_HANDLE(r->in.handle)));
5598                 *r->out.num_written = r->in._data_size;
5599                 return WERR_BADFID;
5600         }
5601
5602         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5603                 return WERR_BADFID;
5604
5605         /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5606         buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5607                                                    snum, Printer->jobid,
5608                                                    (const char *)r->in.data.data,
5609                                                    (size_t)r->in._data_size);
5610         if (buffer_written == (ssize_t)-1) {
5611                 *r->out.num_written = 0;
5612                 if (errno == ENOSPC)
5613                         return WERR_NO_SPOOL_SPACE;
5614                 else
5615                         return WERR_ACCESS_DENIED;
5616         }
5617
5618         *r->out.num_written = r->in._data_size;
5619
5620         return WERR_OK;
5621 }
5622
5623 /********************************************************************
5624  * api_spoolss_getprinter
5625  * called from the spoolss dispatcher
5626  *
5627  ********************************************************************/
5628
5629 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5630                               struct pipes_struct *p)
5631 {
5632         const struct auth_serversupplied_info *server_info = get_server_info_system();
5633         int snum;
5634         WERROR errcode = WERR_BADFUNC;
5635         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5636
5637         if (!Printer) {
5638                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5639                         OUR_HANDLE(handle)));
5640                 return WERR_BADFID;
5641         }
5642
5643         if (!get_printer_snum(p, handle, &snum, NULL))
5644                 return WERR_BADFID;
5645
5646         switch (command) {
5647         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5648                 errcode = print_queue_pause(server_info, p->msg_ctx, snum);
5649                 break;
5650         case SPOOLSS_PRINTER_CONTROL_RESUME:
5651         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5652                 errcode = print_queue_resume(server_info, p->msg_ctx, snum);
5653                 break;
5654         case SPOOLSS_PRINTER_CONTROL_PURGE:
5655                 errcode = print_queue_purge(server_info, p->msg_ctx, snum);
5656                 break;
5657         default:
5658                 return WERR_UNKNOWN_LEVEL;
5659         }
5660
5661         return errcode;
5662 }
5663
5664
5665 /****************************************************************
5666  _spoolss_AbortPrinter
5667  * From MSDN: "Deletes printer's spool file if printer is configured
5668  * for spooling"
5669 ****************************************************************/
5670
5671 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
5672                              struct spoolss_AbortPrinter *r)
5673 {
5674         struct printer_handle   *Printer = find_printer_index_by_hnd(p, r->in.handle);
5675         int             snum;
5676         WERROR          errcode = WERR_OK;
5677
5678         if (!Printer) {
5679                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5680                         OUR_HANDLE(r->in.handle)));
5681                 return WERR_BADFID;
5682         }
5683
5684         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5685                 return WERR_BADFID;
5686
5687         if (!Printer->document_started) {
5688                 return WERR_SPL_NO_STARTDOC;
5689         }
5690
5691         errcode = print_job_delete(get_server_info_system(),
5692                                    p->msg_ctx,
5693                                    snum,
5694                                    Printer->jobid);
5695
5696         return errcode;
5697 }
5698
5699 /********************************************************************
5700  * called by spoolss_api_setprinter
5701  * when updating a printer description
5702  ********************************************************************/
5703
5704 static WERROR update_printer_sec(struct policy_handle *handle,
5705                                  struct pipes_struct *p,
5706                                  struct sec_desc_buf *secdesc_ctr)
5707 {
5708         struct spoolss_security_descriptor *new_secdesc = NULL;
5709         struct spoolss_security_descriptor *old_secdesc = NULL;
5710         const char *printer;
5711         WERROR result;
5712         int snum;
5713
5714         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5715
5716         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5717                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5718                          OUR_HANDLE(handle)));
5719
5720                 result = WERR_BADFID;
5721                 goto done;
5722         }
5723
5724         if (secdesc_ctr == NULL) {
5725                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5726                 result = WERR_INVALID_PARAM;
5727                 goto done;
5728         }
5729         printer = lp_const_servicename(snum);
5730
5731         /* Check the user has permissions to change the security
5732            descriptor.  By experimentation with two NT machines, the user
5733            requires Full Access to the printer to change security
5734            information. */
5735
5736         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5737                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5738                 result = WERR_ACCESS_DENIED;
5739                 goto done;
5740         }
5741
5742         /* NT seems to like setting the security descriptor even though
5743            nothing may have actually changed. */
5744         result = winreg_get_printer_secdesc(p->mem_ctx,
5745                                             get_server_info_system(),
5746                                             p->msg_ctx,
5747                                             printer,
5748                                             &old_secdesc);
5749         if (!W_ERROR_IS_OK(result)) {
5750                 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc() failed\n"));
5751                 result = WERR_BADFID;
5752                 goto done;
5753         }
5754
5755         if (DEBUGLEVEL >= 10) {
5756                 struct security_acl *the_acl;
5757                 int i;
5758
5759                 the_acl = old_secdesc->dacl;
5760                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5761                            printer, the_acl->num_aces));
5762
5763                 for (i = 0; i < the_acl->num_aces; i++) {
5764                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5765                                            &the_acl->aces[i].trustee),
5766                                   the_acl->aces[i].access_mask));
5767                 }
5768
5769                 the_acl = secdesc_ctr->sd->dacl;
5770
5771                 if (the_acl) {
5772                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5773                                    printer, the_acl->num_aces));
5774
5775                         for (i = 0; i < the_acl->num_aces; i++) {
5776                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5777                                                    &the_acl->aces[i].trustee),
5778                                            the_acl->aces[i].access_mask));
5779                         }
5780                 } else {
5781                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5782                 }
5783         }
5784
5785         new_secdesc = sec_desc_merge(p->mem_ctx, secdesc_ctr->sd, old_secdesc);
5786         if (new_secdesc == NULL) {
5787                 result = WERR_NOMEM;
5788                 goto done;
5789         }
5790
5791         if (security_descriptor_equal(new_secdesc, old_secdesc)) {
5792                 result = WERR_OK;
5793                 goto done;
5794         }
5795
5796         result = winreg_set_printer_secdesc(p->mem_ctx,
5797                                             get_server_info_system(),
5798                                             p->msg_ctx,
5799                                             printer,
5800                                             new_secdesc);
5801
5802  done:
5803         return result;
5804 }
5805
5806 /********************************************************************
5807  Canonicalize printer info from a client
5808  ********************************************************************/
5809
5810 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
5811                              struct spoolss_SetPrinterInfo2 *info2,
5812                              int snum)
5813 {
5814         fstring printername;
5815         const char *p;
5816
5817         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5818                 "portname=%s drivername=%s comment=%s location=%s\n",
5819                 info2->servername, info2->printername, info2->sharename,
5820                 info2->portname, info2->drivername, info2->comment,
5821                 info2->location));
5822
5823         /* we force some elements to "correct" values */
5824         info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
5825         if (info2->servername == NULL) {
5826                 return false;
5827         }
5828         info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
5829         if (info2->sharename == NULL) {
5830                 return false;
5831         }
5832
5833         /* check to see if we allow printername != sharename */
5834         if (lp_force_printername(snum)) {
5835                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
5836                                         global_myname(), info2->sharename);
5837         } else {
5838                 /* make sure printername is in \\server\printername format */
5839                 fstrcpy(printername, info2->printername);
5840                 p = printername;
5841                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5842                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5843                                 p++;
5844                 }
5845
5846                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
5847                                         global_myname(), p);
5848         }
5849         if (info2->printername == NULL) {
5850                 return false;
5851         }
5852
5853         info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5854         info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5855
5856         return true;
5857 }
5858
5859 /****************************************************************************
5860 ****************************************************************************/
5861
5862 static WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri)
5863 {
5864         char *cmd = lp_addport_cmd();
5865         char *command = NULL;
5866         int ret;
5867         uint64_t se_printop = SE_PRINT_OPERATOR;
5868         bool is_print_op = false;
5869
5870         if ( !*cmd ) {
5871                 return WERR_ACCESS_DENIED;
5872         }
5873
5874         command = talloc_asprintf(ctx,
5875                         "%s \"%s\" \"%s\"", cmd, portname, uri );
5876         if (!command) {
5877                 return WERR_NOMEM;
5878         }
5879
5880         if ( token )
5881                 is_print_op = user_has_privileges( token, &se_printop );
5882
5883         DEBUG(10,("Running [%s]\n", command));
5884
5885         /********* BEGIN SePrintOperatorPrivilege **********/
5886
5887         if ( is_print_op )
5888                 become_root();
5889
5890         ret = smbrun(command, NULL);
5891
5892         if ( is_print_op )
5893                 unbecome_root();
5894
5895         /********* END SePrintOperatorPrivilege **********/
5896
5897         DEBUGADD(10,("returned [%d]\n", ret));
5898
5899         TALLOC_FREE(command);
5900
5901         if ( ret != 0 ) {
5902                 return WERR_ACCESS_DENIED;
5903         }
5904
5905         return WERR_OK;
5906 }
5907
5908 /****************************************************************************
5909 ****************************************************************************/
5910
5911 static bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token,
5912                              struct spoolss_SetPrinterInfo2 *info2,
5913                              const char *remote_machine,
5914                              struct messaging_context *msg_ctx)
5915 {
5916         char *cmd = lp_addprinter_cmd();
5917         char **qlines;
5918         char *command = NULL;
5919         int numlines;
5920         int ret;
5921         int fd;
5922         uint64_t se_printop = SE_PRINT_OPERATOR;
5923         bool is_print_op = false;
5924
5925         if (!remote_machine) {
5926                 return false;
5927         }
5928
5929         command = talloc_asprintf(ctx,
5930                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5931                         cmd, info2->printername, info2->sharename,
5932                         info2->portname, info2->drivername,
5933                         info2->location, info2->comment, remote_machine);
5934         if (!command) {
5935                 return false;
5936         }
5937
5938         if ( token )
5939                 is_print_op = user_has_privileges( token, &se_printop );
5940
5941         DEBUG(10,("Running [%s]\n", command));
5942
5943         /********* BEGIN SePrintOperatorPrivilege **********/
5944
5945         if ( is_print_op )
5946                 become_root();
5947
5948         if ( (ret = smbrun(command, &fd)) == 0 ) {
5949                 /* Tell everyone we updated smb.conf. */
5950                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
5951         }
5952
5953         if ( is_print_op )
5954                 unbecome_root();
5955
5956         /********* END SePrintOperatorPrivilege **********/
5957
5958         DEBUGADD(10,("returned [%d]\n", ret));
5959
5960         TALLOC_FREE(command);
5961
5962         if ( ret != 0 ) {
5963                 if (fd != -1)
5964                         close(fd);
5965                 return false;
5966         }
5967
5968         /* reload our services immediately */
5969         become_root();
5970         reload_services(msg_ctx, -1, false);
5971         unbecome_root();
5972
5973         numlines = 0;
5974         /* Get lines and convert them back to dos-codepage */
5975         qlines = fd_lines_load(fd, &numlines, 0, NULL);
5976         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
5977         close(fd);
5978
5979         /* Set the portname to what the script says the portname should be. */
5980         /* but don't require anything to be return from the script exit a good error code */
5981
5982         if (numlines) {
5983                 /* Set the portname to what the script says the portname should be. */
5984                 info2->portname = talloc_strdup(ctx, qlines[0]);
5985                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
5986         }
5987
5988         TALLOC_FREE(qlines);
5989         return true;
5990 }
5991
5992 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
5993                                const struct auth_serversupplied_info *server_info,
5994                                struct messaging_context *msg_ctx,
5995                                int snum,
5996                                struct spoolss_SetPrinterInfo2 *printer,
5997                                struct spoolss_PrinterInfo2 *old_printer)
5998 {
5999         bool force_update = (old_printer == NULL);
6000         const char *dnsdomname;
6001         const char *longname;
6002         const char *uncname;
6003         const char *spooling;
6004         DATA_BLOB buffer;
6005         WERROR result = WERR_OK;
6006
6007         if (force_update || !strequal(printer->drivername, old_printer->drivername)) {
6008                 push_reg_sz(mem_ctx, &buffer, printer->drivername);
6009                 winreg_set_printer_dataex(mem_ctx,
6010                                           server_info,
6011                                           msg_ctx,
6012                                           printer->sharename,
6013                                           SPOOL_DSSPOOLER_KEY,
6014                                           SPOOL_REG_DRIVERNAME,
6015                                           REG_SZ,
6016                                           buffer.data,
6017                                           buffer.length);
6018
6019                 if (!force_update) {
6020                         DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6021                                 printer->drivername));
6022
6023                         notify_printer_driver(server_event_context(), msg_ctx,
6024                                               snum, printer->drivername);
6025                 }
6026         }
6027
6028         if (force_update || !strequal(printer->comment, old_printer->comment)) {
6029                 push_reg_sz(mem_ctx, &buffer, printer->comment);
6030                 winreg_set_printer_dataex(mem_ctx,
6031                                           server_info,
6032                                           msg_ctx,
6033                                           printer->sharename,
6034                                           SPOOL_DSSPOOLER_KEY,
6035                                           SPOOL_REG_DESCRIPTION,
6036                                           REG_SZ,
6037                                           buffer.data,
6038                                           buffer.length);
6039
6040                 if (!force_update) {
6041                         notify_printer_comment(server_event_context(), msg_ctx,
6042                                                snum, printer->comment);
6043                 }
6044         }
6045
6046         if (force_update || !strequal(printer->sharename, old_printer->sharename)) {
6047                 push_reg_sz(mem_ctx, &buffer, printer->sharename);
6048                 winreg_set_printer_dataex(mem_ctx,
6049                                           server_info,
6050                                           msg_ctx,
6051                                           printer->sharename,
6052                                           SPOOL_DSSPOOLER_KEY,
6053                                           SPOOL_REG_PRINTSHARENAME,
6054                                           REG_SZ,
6055                                           buffer.data,
6056                                           buffer.length);
6057
6058                 if (!force_update) {
6059                         notify_printer_sharename(server_event_context(),
6060                                                  msg_ctx,
6061                                                  snum, printer->sharename);
6062                 }
6063         }
6064
6065         if (force_update || !strequal(printer->printername, old_printer->printername)) {
6066                 const char *p;
6067
6068                 p = strrchr(printer->printername, '\\' );
6069                 if (p != NULL) {
6070                         p++;
6071                 } else {
6072                         p = printer->printername;
6073                 }
6074
6075                 push_reg_sz(mem_ctx, &buffer, p);
6076                 winreg_set_printer_dataex(mem_ctx,
6077                                           server_info,
6078                                           msg_ctx,
6079                                           printer->sharename,
6080                                           SPOOL_DSSPOOLER_KEY,
6081                                           SPOOL_REG_PRINTERNAME,
6082                                           REG_SZ,
6083                                           buffer.data,
6084                                           buffer.length);
6085
6086                 if (!force_update) {
6087                         notify_printer_printername(server_event_context(),
6088                                                    msg_ctx, snum, p);
6089                 }
6090         }
6091
6092         if (force_update || !strequal(printer->portname, old_printer->portname)) {
6093                 push_reg_sz(mem_ctx, &buffer, printer->portname);
6094                 winreg_set_printer_dataex(mem_ctx,
6095                                           server_info,
6096                                           msg_ctx,
6097                                           printer->sharename,
6098                                           SPOOL_DSSPOOLER_KEY,
6099                                           SPOOL_REG_PORTNAME,
6100                                           REG_SZ,
6101                                           buffer.data,
6102                                           buffer.length);
6103
6104                 if (!force_update) {
6105                         notify_printer_port(server_event_context(),
6106                                             msg_ctx, snum, printer->portname);
6107                 }
6108         }
6109
6110         if (force_update || !strequal(printer->location, old_printer->location)) {
6111                 push_reg_sz(mem_ctx, &buffer, printer->location);
6112                 winreg_set_printer_dataex(mem_ctx,
6113                                           server_info,
6114                                           msg_ctx,
6115                                           printer->sharename,
6116                                           SPOOL_DSSPOOLER_KEY,
6117                                           SPOOL_REG_LOCATION,
6118                                           REG_SZ,
6119                                           buffer.data,
6120                                           buffer.length);
6121
6122                 if (!force_update) {
6123                         notify_printer_location(server_event_context(),
6124                                                 msg_ctx, snum,
6125                                                 printer->location);
6126                 }
6127         }
6128
6129         if (force_update || !strequal(printer->sepfile, old_printer->sepfile)) {
6130                 push_reg_sz(mem_ctx, &buffer, printer->sepfile);
6131                 winreg_set_printer_dataex(mem_ctx,
6132                                           server_info,
6133                                           msg_ctx,
6134                                           printer->sharename,
6135                                           SPOOL_DSSPOOLER_KEY,
6136                                           SPOOL_REG_PRINTSEPARATORFILE,
6137                                           REG_SZ,
6138                                           buffer.data,
6139                                           buffer.length);
6140
6141                 if (!force_update) {
6142                         notify_printer_location(server_event_context(),
6143                                                 msg_ctx, snum,
6144                                                 printer->location);
6145                 }
6146         }
6147
6148         if (force_update || printer->starttime != old_printer->starttime) {
6149                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6150                 SIVAL(buffer.data, 0, printer->starttime);
6151                 winreg_set_printer_dataex(mem_ctx,
6152                                           server_info,
6153                                           msg_ctx,
6154                                           printer->sharename,
6155                                           SPOOL_DSSPOOLER_KEY,
6156                                           SPOOL_REG_PRINTSTARTTIME,
6157                                           REG_DWORD,
6158                                           buffer.data,
6159                                           buffer.length);
6160         }
6161
6162         if (force_update || printer->untiltime != old_printer->untiltime) {
6163                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6164                 SIVAL(buffer.data, 0, printer->untiltime);
6165                 winreg_set_printer_dataex(mem_ctx,
6166                                           server_info,
6167                                           msg_ctx,
6168                                           printer->sharename,
6169                                           SPOOL_DSSPOOLER_KEY,
6170                                           SPOOL_REG_PRINTENDTIME,
6171                                           REG_DWORD,
6172                                           buffer.data,
6173                                           buffer.length);
6174         }
6175
6176         if (force_update || printer->priority != old_printer->priority) {
6177                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6178                 SIVAL(buffer.data, 0, printer->priority);
6179                 winreg_set_printer_dataex(mem_ctx,
6180                                           server_info,
6181                                           msg_ctx,
6182                                           printer->sharename,
6183                                           SPOOL_DSSPOOLER_KEY,
6184                                           SPOOL_REG_PRIORITY,
6185                                           REG_DWORD,
6186                                           buffer.data,
6187                                           buffer.length);
6188         }
6189
6190         if (force_update || printer->attributes != old_printer->attributes) {
6191                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6192                 SIVAL(buffer.data, 0, (printer->attributes &
6193                                        PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6194                 winreg_set_printer_dataex(mem_ctx,
6195                                           server_info,
6196                                           msg_ctx,
6197                                           printer->sharename,
6198                                           SPOOL_DSSPOOLER_KEY,
6199                                           SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6200                                           REG_DWORD,
6201                                           buffer.data,
6202                                           buffer.length);
6203
6204                 switch (printer->attributes & 0x3) {
6205                         case 0:
6206                                 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6207                                 break;
6208                         case 1:
6209                                 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6210                                 break;
6211                         case 2:
6212                                 spooling = SPOOL_REGVAL_PRINTDIRECT;
6213                                 break;
6214                         default:
6215                                 spooling = "unknown";
6216                 }
6217                 push_reg_sz(mem_ctx, &buffer, spooling);
6218                 winreg_set_printer_dataex(mem_ctx,
6219                                           server_info,
6220                                           msg_ctx,
6221                                           printer->sharename,
6222                                           SPOOL_DSSPOOLER_KEY,
6223                                           SPOOL_REG_PRINTSPOOLING,
6224                                           REG_SZ,
6225                                           buffer.data,
6226                                           buffer.length);
6227         }
6228
6229         push_reg_sz(mem_ctx, &buffer, global_myname());
6230         winreg_set_printer_dataex(mem_ctx,
6231                                   server_info,
6232                                   msg_ctx,
6233                                   printer->sharename,
6234                                   SPOOL_DSSPOOLER_KEY,
6235                                   SPOOL_REG_SHORTSERVERNAME,
6236                                   REG_SZ,
6237                                   buffer.data,
6238                                   buffer.length);
6239
6240         dnsdomname = get_mydnsfullname();
6241         if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6242                 longname = talloc_strdup(mem_ctx, dnsdomname);
6243         } else {
6244                 longname = talloc_strdup(mem_ctx, global_myname());
6245         }
6246         if (longname == NULL) {
6247                 result = WERR_NOMEM;
6248                 goto done;
6249         }
6250
6251         push_reg_sz(mem_ctx, &buffer, longname);
6252         winreg_set_printer_dataex(mem_ctx,
6253                                   server_info,
6254                                   msg_ctx,
6255                                   printer->sharename,
6256                                   SPOOL_DSSPOOLER_KEY,
6257                                   SPOOL_REG_SERVERNAME,
6258                                   REG_SZ,
6259                                   buffer.data,
6260                                   buffer.length);
6261
6262         uncname = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6263                                   global_myname(), printer->sharename);
6264         push_reg_sz(mem_ctx, &buffer, uncname);
6265         winreg_set_printer_dataex(mem_ctx,
6266                                   server_info,
6267                                   msg_ctx,
6268                                   printer->sharename,
6269                                   SPOOL_DSSPOOLER_KEY,
6270                                   SPOOL_REG_UNCNAME,
6271                                   REG_SZ,
6272                                   buffer.data,
6273                                   buffer.length);
6274
6275 done:
6276         return result;
6277 }
6278
6279 /********************************************************************
6280  * Called by spoolss_api_setprinter
6281  * when updating a printer description.
6282  ********************************************************************/
6283
6284 static WERROR update_printer(struct pipes_struct *p,
6285                              struct policy_handle *handle,
6286                              struct spoolss_SetPrinterInfoCtr *info_ctr,
6287                              struct spoolss_DeviceMode *devmode)
6288 {
6289         uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6290         struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6291         struct spoolss_PrinterInfo2 *old_printer;
6292         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6293         const char *servername = NULL;
6294         int snum;
6295         WERROR result = WERR_OK;
6296         TALLOC_CTX *tmp_ctx;
6297
6298         DEBUG(8,("update_printer\n"));
6299
6300         tmp_ctx = talloc_new(p->mem_ctx);
6301         if (tmp_ctx == NULL) {
6302                 return WERR_NOMEM;
6303         }
6304
6305         if (!Printer) {
6306                 result = WERR_BADFID;
6307                 goto done;
6308         }
6309
6310         if (!get_printer_snum(p, handle, &snum, NULL)) {
6311                 result = WERR_BADFID;
6312                 goto done;
6313         }
6314
6315         if (Printer != NULL || Printer->servername != NULL) {
6316                 servername = Printer->servername;
6317         }
6318
6319         result = winreg_get_printer(tmp_ctx,
6320                                     get_server_info_system(),
6321                                     p->msg_ctx,
6322                                     servername,
6323                                     lp_const_servicename(snum),
6324                                     &old_printer);
6325         if (!W_ERROR_IS_OK(result)) {
6326                 result = WERR_BADFID;
6327                 goto done;
6328         }
6329
6330         /* Do sanity check on the requested changes for Samba */
6331         if (!check_printer_ok(tmp_ctx, printer, snum)) {
6332                 result = WERR_INVALID_PARAM;
6333                 goto done;
6334         }
6335
6336         /* FIXME!!! If the driver has changed we really should verify that
6337            it is installed before doing much else   --jerry */
6338
6339         /* Check calling user has permission to update printer description */
6340         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6341                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6342                 result = WERR_ACCESS_DENIED;
6343                 goto done;
6344         }
6345
6346         /* Call addprinter hook */
6347         /* Check changes to see if this is really needed */
6348
6349         if (*lp_addprinter_cmd() &&
6350                         (!strequal(printer->drivername, old_printer->drivername) ||
6351                          !strequal(printer->comment, old_printer->comment) ||
6352                          !strequal(printer->portname, old_printer->portname) ||
6353                          !strequal(printer->location, old_printer->location)) )
6354         {
6355                 /* add_printer_hook() will call reload_services() */
6356                 if (!add_printer_hook(tmp_ctx, p->server_info->ptok,
6357                                       printer, p->client_id->addr,
6358                                       p->msg_ctx)) {
6359                         result = WERR_ACCESS_DENIED;
6360                         goto done;
6361                 }
6362         }
6363
6364         update_dsspooler(tmp_ctx,
6365                          get_server_info_system(),
6366                          p->msg_ctx,
6367                          snum,
6368                          printer,
6369                          old_printer);
6370
6371         printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6372
6373         if (devmode == NULL) {
6374                 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6375         }
6376         result = winreg_update_printer(tmp_ctx,
6377                                        get_server_info_system(),
6378                                        p->msg_ctx,
6379                                        printer->sharename,
6380                                        printer_mask,
6381                                        printer,
6382                                        devmode,
6383                                        NULL);
6384
6385 done:
6386         talloc_free(tmp_ctx);
6387
6388         return result;
6389 }
6390
6391 /****************************************************************************
6392 ****************************************************************************/
6393 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6394                                            struct policy_handle *handle,
6395                                            struct spoolss_SetPrinterInfo7 *info7)
6396 {
6397 #ifdef HAVE_ADS
6398         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6399         WERROR result;
6400         int snum;
6401         struct printer_handle *Printer;
6402
6403         if ( lp_security() != SEC_ADS ) {
6404                 return WERR_UNKNOWN_LEVEL;
6405         }
6406
6407         Printer = find_printer_index_by_hnd(p, handle);
6408
6409         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6410
6411         if (!Printer)
6412                 return WERR_BADFID;
6413
6414         if (!get_printer_snum(p, handle, &snum, NULL))
6415                 return WERR_BADFID;
6416
6417         result = winreg_get_printer(p->mem_ctx,
6418                                     get_server_info_system(),
6419                                     p->msg_ctx,
6420                                     Printer->servername,
6421                                     lp_servicename(snum),
6422                                     &pinfo2);
6423         if (!W_ERROR_IS_OK(result)) {
6424                 return WERR_BADFID;
6425         }
6426
6427         nt_printer_publish(pinfo2,
6428                            get_server_info_system(),
6429                            p->msg_ctx,
6430                            pinfo2,
6431                            info7->action);
6432
6433         TALLOC_FREE(pinfo2);
6434         return WERR_OK;
6435 #else
6436         return WERR_UNKNOWN_LEVEL;
6437 #endif
6438 }
6439
6440 /********************************************************************
6441  ********************************************************************/
6442
6443 static WERROR update_printer_devmode(struct pipes_struct *p,
6444                                      struct policy_handle *handle,
6445                                      struct spoolss_DeviceMode *devmode)
6446 {
6447         int snum;
6448         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6449         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6450
6451         DEBUG(8,("update_printer_devmode\n"));
6452
6453         if (!Printer) {
6454                 return WERR_BADFID;
6455         }
6456
6457         if (!get_printer_snum(p, handle, &snum, NULL)) {
6458                 return WERR_BADFID;
6459         }
6460
6461         /* Check calling user has permission to update printer description */
6462         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6463                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6464                 return WERR_ACCESS_DENIED;
6465         }
6466
6467         return winreg_update_printer(p->mem_ctx,
6468                                      get_server_info_system(),
6469                                      p->msg_ctx,
6470                                      lp_const_servicename(snum),
6471                                      info2_mask,
6472                                      NULL,
6473                                      devmode,
6474                                      NULL);
6475 }
6476
6477
6478 /****************************************************************
6479  _spoolss_SetPrinter
6480 ****************************************************************/
6481
6482 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6483                            struct spoolss_SetPrinter *r)
6484 {
6485         WERROR result;
6486
6487         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6488
6489         if (!Printer) {
6490                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6491                         OUR_HANDLE(r->in.handle)));
6492                 return WERR_BADFID;
6493         }
6494
6495         /* check the level */
6496         switch (r->in.info_ctr->level) {
6497                 case 0:
6498                         return control_printer(r->in.handle, r->in.command, p);
6499                 case 2:
6500                         result = update_printer(p, r->in.handle,
6501                                                 r->in.info_ctr,
6502                                                 r->in.devmode_ctr->devmode);
6503                         if (!W_ERROR_IS_OK(result))
6504                                 return result;
6505                         if (r->in.secdesc_ctr->sd)
6506                                 result = update_printer_sec(r->in.handle, p,
6507                                                             r->in.secdesc_ctr);
6508                         return result;
6509                 case 3:
6510                         return update_printer_sec(r->in.handle, p,
6511                                                   r->in.secdesc_ctr);
6512                 case 7:
6513                         return publish_or_unpublish_printer(p, r->in.handle,
6514                                                             r->in.info_ctr->info.info7);
6515                 case 8:
6516                         return update_printer_devmode(p, r->in.handle,
6517                                                       r->in.devmode_ctr->devmode);
6518                 default:
6519                         return WERR_UNKNOWN_LEVEL;
6520         }
6521 }
6522
6523 /****************************************************************
6524  _spoolss_FindClosePrinterNotify
6525 ****************************************************************/
6526
6527 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
6528                                        struct spoolss_FindClosePrinterNotify *r)
6529 {
6530         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6531
6532         if (!Printer) {
6533                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6534                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6535                 return WERR_BADFID;
6536         }
6537
6538         if (Printer->notify.cli_chan != NULL &&
6539             Printer->notify.cli_chan->active_connections > 0) {
6540                 int snum = -1;
6541
6542                 if (Printer->printer_type == SPLHND_PRINTER) {
6543                         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6544                                 return WERR_BADFID;
6545                         }
6546                 }
6547
6548                 srv_spoolss_replycloseprinter(snum, Printer);
6549         }
6550
6551         Printer->notify.flags=0;
6552         Printer->notify.options=0;
6553         Printer->notify.localmachine[0]='\0';
6554         Printer->notify.printerlocal=0;
6555         TALLOC_FREE(Printer->notify.option);
6556
6557         return WERR_OK;
6558 }
6559
6560 /****************************************************************
6561  _spoolss_AddJob
6562 ****************************************************************/
6563
6564 WERROR _spoolss_AddJob(struct pipes_struct *p,
6565                        struct spoolss_AddJob *r)
6566 {
6567         if (!r->in.buffer && (r->in.offered != 0)) {
6568                 return WERR_INVALID_PARAM;
6569         }
6570
6571         /* this is what a NT server returns for AddJob. AddJob must fail on
6572          * non-local printers */
6573
6574         if (r->in.level != 1) {
6575                 return WERR_UNKNOWN_LEVEL;
6576         }
6577
6578         return WERR_INVALID_PARAM;
6579 }
6580
6581 /****************************************************************************
6582 fill_job_info1
6583 ****************************************************************************/
6584
6585 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6586                              struct spoolss_JobInfo1 *r,
6587                              const print_queue_struct *queue,
6588                              int position, int snum,
6589                              struct spoolss_PrinterInfo2 *pinfo2)
6590 {
6591         struct tm *t;
6592
6593         t = gmtime(&queue->time);
6594
6595         r->job_id               = queue->job;
6596
6597         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6598         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6599         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
6600         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6601         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6602         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6603         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6604         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6605         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6606         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6607         r->text_status          = talloc_strdup(mem_ctx, "");
6608         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6609
6610         r->status               = nt_printj_status(queue->status);
6611         r->priority             = queue->priority;
6612         r->position             = position;
6613         r->total_pages          = queue->page_count;
6614         r->pages_printed        = 0; /* ??? */
6615
6616         init_systemtime(&r->submitted, t);
6617
6618         return WERR_OK;
6619 }
6620
6621 /****************************************************************************
6622 fill_job_info2
6623 ****************************************************************************/
6624
6625 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6626                              struct spoolss_JobInfo2 *r,
6627                              const print_queue_struct *queue,
6628                              int position, int snum,
6629                              struct spoolss_PrinterInfo2 *pinfo2,
6630                              struct spoolss_DeviceMode *devmode)
6631 {
6632         struct tm *t;
6633
6634         t = gmtime(&queue->time);
6635
6636         r->job_id               = queue->job;
6637
6638         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6639         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6640         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
6641         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6642         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6643         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6644         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6645         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6646         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
6647         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6648         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6649         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6650         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
6651         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6652         r->parameters           = talloc_strdup(mem_ctx, "");
6653         W_ERROR_HAVE_NO_MEMORY(r->parameters);
6654         r->driver_name          = talloc_strdup(mem_ctx, pinfo2->drivername);
6655         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6656
6657         r->devmode              = devmode;
6658
6659         r->text_status          = talloc_strdup(mem_ctx, "");
6660         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6661
6662         r->secdesc              = NULL;
6663
6664         r->status               = nt_printj_status(queue->status);
6665         r->priority             = queue->priority;
6666         r->position             = position;
6667         r->start_time           = 0;
6668         r->until_time           = 0;
6669         r->total_pages          = queue->page_count;
6670         r->size                 = queue->size;
6671         init_systemtime(&r->submitted, t);
6672         r->time                 = 0;
6673         r->pages_printed        = 0; /* ??? */
6674
6675         return WERR_OK;
6676 }
6677
6678 /****************************************************************************
6679 fill_job_info3
6680 ****************************************************************************/
6681
6682 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6683                              struct spoolss_JobInfo3 *r,
6684                              const print_queue_struct *queue,
6685                              const print_queue_struct *next_queue,
6686                              int position, int snum,
6687                              struct spoolss_PrinterInfo2 *pinfo2)
6688 {
6689         r->job_id               = queue->job;
6690         r->next_job_id          = 0;
6691         if (next_queue) {
6692                 r->next_job_id  = next_queue->job;
6693         }
6694         r->reserved             = 0;
6695
6696         return WERR_OK;
6697 }
6698
6699 /****************************************************************************
6700  Enumjobs at level 1.
6701 ****************************************************************************/
6702
6703 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6704                               const print_queue_struct *queue,
6705                               uint32_t num_queues, int snum,
6706                               struct spoolss_PrinterInfo2 *pinfo2,
6707                               union spoolss_JobInfo **info_p,
6708                               uint32_t *count)
6709 {
6710         union spoolss_JobInfo *info;
6711         int i;
6712         WERROR result = WERR_OK;
6713
6714         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6715         W_ERROR_HAVE_NO_MEMORY(info);
6716
6717         *count = num_queues;
6718
6719         for (i=0; i<*count; i++) {
6720                 result = fill_job_info1(info,
6721                                         &info[i].info1,
6722                                         &queue[i],
6723                                         i,
6724                                         snum,
6725                                         pinfo2);
6726                 if (!W_ERROR_IS_OK(result)) {
6727                         goto out;
6728                 }
6729         }
6730
6731  out:
6732         if (!W_ERROR_IS_OK(result)) {
6733                 TALLOC_FREE(info);
6734                 *count = 0;
6735                 return result;
6736         }
6737
6738         *info_p = info;
6739
6740         return WERR_OK;
6741 }
6742
6743 /****************************************************************************
6744  Enumjobs at level 2.
6745 ****************************************************************************/
6746
6747 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6748                               const print_queue_struct *queue,
6749                               uint32_t num_queues, int snum,
6750                               struct spoolss_PrinterInfo2 *pinfo2,
6751                               union spoolss_JobInfo **info_p,
6752                               uint32_t *count)
6753 {
6754         union spoolss_JobInfo *info;
6755         int i;
6756         WERROR result = WERR_OK;
6757
6758         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6759         W_ERROR_HAVE_NO_MEMORY(info);
6760
6761         *count = num_queues;
6762
6763         for (i=0; i<*count; i++) {
6764                 struct spoolss_DeviceMode *devmode;
6765
6766                 result = spoolss_create_default_devmode(info,
6767                                                         pinfo2->printername,
6768                                                         &devmode);
6769                 if (!W_ERROR_IS_OK(result)) {
6770                         DEBUG(3, ("Can't proceed w/o a devmode!"));
6771                         goto out;
6772                 }
6773
6774                 result = fill_job_info2(info,
6775                                         &info[i].info2,
6776                                         &queue[i],
6777                                         i,
6778                                         snum,
6779                                         pinfo2,
6780                                         devmode);
6781                 if (!W_ERROR_IS_OK(result)) {
6782                         goto out;
6783                 }
6784         }
6785
6786  out:
6787         if (!W_ERROR_IS_OK(result)) {
6788                 TALLOC_FREE(info);
6789                 *count = 0;
6790                 return result;
6791         }
6792
6793         *info_p = info;
6794
6795         return WERR_OK;
6796 }
6797
6798 /****************************************************************************
6799  Enumjobs at level 3.
6800 ****************************************************************************/
6801
6802 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
6803                               const print_queue_struct *queue,
6804                               uint32_t num_queues, int snum,
6805                               struct spoolss_PrinterInfo2 *pinfo2,
6806                               union spoolss_JobInfo **info_p,
6807                               uint32_t *count)
6808 {
6809         union spoolss_JobInfo *info;
6810         int i;
6811         WERROR result = WERR_OK;
6812
6813         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6814         W_ERROR_HAVE_NO_MEMORY(info);
6815
6816         *count = num_queues;
6817
6818         for (i=0; i<*count; i++) {
6819                 const print_queue_struct *next_queue = NULL;
6820
6821                 if (i+1 < *count) {
6822                         next_queue = &queue[i+1];
6823                 }
6824
6825                 result = fill_job_info3(info,
6826                                         &info[i].info3,
6827                                         &queue[i],
6828                                         next_queue,
6829                                         i,
6830                                         snum,
6831                                         pinfo2);
6832                 if (!W_ERROR_IS_OK(result)) {
6833                         goto out;
6834                 }
6835         }
6836
6837  out:
6838         if (!W_ERROR_IS_OK(result)) {
6839                 TALLOC_FREE(info);
6840                 *count = 0;
6841                 return result;
6842         }
6843
6844         *info_p = info;
6845
6846         return WERR_OK;
6847 }
6848
6849 /****************************************************************
6850  _spoolss_EnumJobs
6851 ****************************************************************/
6852
6853 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
6854                          struct spoolss_EnumJobs *r)
6855 {
6856         WERROR result;
6857         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6858         int snum;
6859         print_status_struct prt_status;
6860         print_queue_struct *queue = NULL;
6861         uint32_t count;
6862
6863         /* that's an [in out] buffer */
6864
6865         if (!r->in.buffer && (r->in.offered != 0)) {
6866                 return WERR_INVALID_PARAM;
6867         }
6868
6869         DEBUG(4,("_spoolss_EnumJobs\n"));
6870
6871         *r->out.needed = 0;
6872         *r->out.count = 0;
6873         *r->out.info = NULL;
6874
6875         /* lookup the printer snum and tdb entry */
6876
6877         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6878                 return WERR_BADFID;
6879         }
6880
6881         result = winreg_get_printer(p->mem_ctx,
6882                                     get_server_info_system(),
6883                                     p->msg_ctx,
6884                                     NULL,
6885                                     lp_const_servicename(snum),
6886                                     &pinfo2);
6887         if (!W_ERROR_IS_OK(result)) {
6888                 return result;
6889         }
6890
6891         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
6892         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
6893                 count, prt_status.status, prt_status.message));
6894
6895         if (count == 0) {
6896                 SAFE_FREE(queue);
6897                 TALLOC_FREE(pinfo2);
6898                 return WERR_OK;
6899         }
6900
6901         switch (r->in.level) {
6902         case 1:
6903                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
6904                                          pinfo2, r->out.info, r->out.count);
6905                 break;
6906         case 2:
6907                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
6908                                          pinfo2, r->out.info, r->out.count);
6909                 break;
6910         case 3:
6911                 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
6912                                          pinfo2, r->out.info, r->out.count);
6913                 break;
6914         default:
6915                 result = WERR_UNKNOWN_LEVEL;
6916                 break;
6917         }
6918
6919         SAFE_FREE(queue);
6920         TALLOC_FREE(pinfo2);
6921
6922         if (!W_ERROR_IS_OK(result)) {
6923                 return result;
6924         }
6925
6926         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
6927                                                      spoolss_EnumJobs, 
6928                                                      *r->out.info, r->in.level,
6929                                                      *r->out.count);
6930         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
6931         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
6932
6933         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
6934 }
6935
6936 /****************************************************************
6937  _spoolss_ScheduleJob
6938 ****************************************************************/
6939
6940 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
6941                             struct spoolss_ScheduleJob *r)
6942 {
6943         return WERR_OK;
6944 }
6945
6946 /****************************************************************
6947 ****************************************************************/
6948
6949 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
6950                                struct messaging_context *msg_ctx,
6951                                const char *printer_name,
6952                                uint32_t job_id,
6953                                struct spoolss_SetJobInfo1 *r)
6954 {
6955         char *old_doc_name;
6956
6957         if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
6958                 return WERR_BADFID;
6959         }
6960
6961         if (strequal(old_doc_name, r->document_name)) {
6962                 return WERR_OK;
6963         }
6964
6965         if (!print_job_set_name(server_event_context(), msg_ctx,
6966                                 printer_name, job_id, r->document_name)) {
6967                 return WERR_BADFID;
6968         }
6969
6970         return WERR_OK;
6971 }
6972
6973 /****************************************************************
6974  _spoolss_SetJob
6975 ****************************************************************/
6976
6977 WERROR _spoolss_SetJob(struct pipes_struct *p,
6978                        struct spoolss_SetJob *r)
6979 {
6980         const struct auth_serversupplied_info *server_info = get_server_info_system();
6981         int snum;
6982         WERROR errcode = WERR_BADFUNC;
6983
6984         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6985                 return WERR_BADFID;
6986         }
6987
6988         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
6989                 return WERR_INVALID_PRINTER_NAME;
6990         }
6991
6992         switch (r->in.command) {
6993         case SPOOLSS_JOB_CONTROL_CANCEL:
6994         case SPOOLSS_JOB_CONTROL_DELETE:
6995                 errcode = print_job_delete(server_info, p->msg_ctx,
6996                                            snum, r->in.job_id);
6997                 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
6998                         errcode = WERR_OK;
6999                 }
7000                 break;
7001         case SPOOLSS_JOB_CONTROL_PAUSE:
7002                 if (print_job_pause(server_info, p->msg_ctx,
7003                                     snum, r->in.job_id, &errcode)) {
7004                         errcode = WERR_OK;
7005                 }
7006                 break;
7007         case SPOOLSS_JOB_CONTROL_RESTART:
7008         case SPOOLSS_JOB_CONTROL_RESUME:
7009                 if (print_job_resume(server_info, p->msg_ctx,
7010                                      snum, r->in.job_id, &errcode)) {
7011                         errcode = WERR_OK;
7012                 }
7013                 break;
7014         case 0:
7015                 errcode = WERR_OK;
7016                 break;
7017         default:
7018                 return WERR_UNKNOWN_LEVEL;
7019         }
7020
7021         if (!W_ERROR_IS_OK(errcode)) {
7022                 return errcode;
7023         }
7024
7025         if (r->in.ctr == NULL) {
7026                 return errcode;
7027         }
7028
7029         switch (r->in.ctr->level) {
7030         case 1:
7031                 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7032                                            lp_const_servicename(snum),
7033                                            r->in.job_id,
7034                                            r->in.ctr->info.info1);
7035                 break;
7036         case 2:
7037         case 3:
7038         case 4:
7039         default:
7040                 return WERR_UNKNOWN_LEVEL;
7041         }
7042
7043         return errcode;
7044 }
7045
7046 /****************************************************************************
7047  Enumerates all printer drivers by level and architecture.
7048 ****************************************************************************/
7049
7050 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7051                                                        const struct auth_serversupplied_info *server_info,
7052                                                        struct messaging_context *msg_ctx,
7053                                                        const char *servername,
7054                                                        const char *architecture,
7055                                                        uint32_t level,
7056                                                        union spoolss_DriverInfo **info_p,
7057                                                        uint32_t *count_p)
7058 {
7059         int i;
7060         uint32_t version;
7061         struct spoolss_DriverInfo8 *driver;
7062         union spoolss_DriverInfo *info = NULL;
7063         uint32_t count = 0;
7064         WERROR result = WERR_OK;
7065         uint32_t num_drivers;
7066         const char **drivers;
7067
7068         *count_p = 0;
7069         *info_p = NULL;
7070
7071         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7072                 result = winreg_get_driver_list(mem_ctx, server_info, msg_ctx,
7073                                                 architecture, version,
7074                                                 &num_drivers, &drivers);
7075                 if (!W_ERROR_IS_OK(result)) {
7076                         goto out;
7077                 }
7078                 DEBUG(4, ("we have:[%d] drivers in environment"
7079                           " [%s] and version [%d]\n",
7080                           num_drivers, architecture, version));
7081
7082                 if (num_drivers != 0) {
7083                         info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
7084                                                     union spoolss_DriverInfo,
7085                                                     count + num_drivers);
7086                         if (!info) {
7087                                 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7088                                         "failed to enlarge driver info buffer!\n"));
7089                                 result = WERR_NOMEM;
7090                                 goto out;
7091                         }
7092                 }
7093
7094                 for (i = 0; i < num_drivers; i++) {
7095                         DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7096
7097                         result = winreg_get_driver(mem_ctx, server_info,
7098                                                    msg_ctx,
7099                                                    architecture, drivers[i],
7100                                                    version, &driver);
7101                         if (!W_ERROR_IS_OK(result)) {
7102                                 goto out;
7103                         }
7104
7105                         switch (level) {
7106                         case 1:
7107                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
7108                                                                    driver, servername);
7109                                 break;
7110                         case 2:
7111                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
7112                                                                    driver, servername);
7113                                 break;
7114                         case 3:
7115                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
7116                                                                    driver, servername);
7117                                 break;
7118                         case 4:
7119                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
7120                                                                    driver, servername);
7121                                 break;
7122                         case 5:
7123                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
7124                                                                    driver, servername);
7125                                 break;
7126                         case 6:
7127                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
7128                                                                    driver, servername);
7129                                 break;
7130                         case 8:
7131                                 result = fill_printer_driver_info8(info, &info[count+i].info8,
7132                                                                    driver, servername);
7133                                 break;
7134                         default:
7135                                 result = WERR_UNKNOWN_LEVEL;
7136                                 break;
7137                         }
7138
7139                         TALLOC_FREE(driver);
7140
7141                         if (!W_ERROR_IS_OK(result)) {
7142                                 goto out;
7143                         }
7144                 }
7145
7146                 count += num_drivers;
7147                 TALLOC_FREE(drivers);
7148         }
7149
7150  out:
7151         TALLOC_FREE(drivers);
7152
7153         if (!W_ERROR_IS_OK(result)) {
7154                 TALLOC_FREE(info);
7155                 return result;
7156         }
7157
7158         *info_p = info;
7159         *count_p = count;
7160
7161         return WERR_OK;
7162 }
7163
7164 /****************************************************************************
7165  Enumerates all printer drivers by level.
7166 ****************************************************************************/
7167
7168 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7169                                        const struct auth_serversupplied_info *server_info,
7170                                        struct messaging_context *msg_ctx,
7171                                        const char *servername,
7172                                        const char *architecture,
7173                                        uint32_t level,
7174                                        union spoolss_DriverInfo **info_p,
7175                                        uint32_t *count_p)
7176 {
7177         uint32_t a,i;
7178         WERROR result = WERR_OK;
7179
7180         if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7181
7182                 for (a=0; archi_table[a].long_archi != NULL; a++) {
7183
7184                         union spoolss_DriverInfo *info = NULL;
7185                         uint32_t count = 0;
7186
7187                         result = enumprinterdrivers_level_by_architecture(mem_ctx,
7188                                                                           server_info,
7189                                                                           msg_ctx,
7190                                                                           servername,
7191                                                                           archi_table[a].long_archi,
7192                                                                           level,
7193                                                                           &info,
7194                                                                           &count);
7195                         if (!W_ERROR_IS_OK(result)) {
7196                                 continue;
7197                         }
7198
7199                         for (i=0; i < count; i++) {
7200                                 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7201                                              info[i], info_p, count_p);
7202                         }
7203                 }
7204
7205                 return result;
7206         }
7207
7208         return enumprinterdrivers_level_by_architecture(mem_ctx,
7209                                                         server_info,
7210                                                         msg_ctx,
7211                                                         servername,
7212                                                         architecture,
7213                                                         level,
7214                                                         info_p,
7215                                                         count_p);
7216 }
7217
7218 /****************************************************************
7219  _spoolss_EnumPrinterDrivers
7220 ****************************************************************/
7221
7222 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7223                                    struct spoolss_EnumPrinterDrivers *r)
7224 {
7225         const char *cservername;
7226         WERROR result;
7227
7228         /* that's an [in out] buffer */
7229
7230         if (!r->in.buffer && (r->in.offered != 0)) {
7231                 return WERR_INVALID_PARAM;
7232         }
7233
7234         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7235
7236         *r->out.needed = 0;
7237         *r->out.count = 0;
7238         *r->out.info = NULL;
7239
7240         cservername = canon_servername(r->in.server);
7241
7242         if (!is_myname_or_ipaddr(cservername)) {
7243                 return WERR_UNKNOWN_PRINTER_DRIVER;
7244         }
7245
7246         result = enumprinterdrivers_level(p->mem_ctx,
7247                                           get_server_info_system(),
7248                                           p->msg_ctx,
7249                                           cservername,
7250                                           r->in.environment,
7251                                           r->in.level,
7252                                           r->out.info,
7253                                           r->out.count);
7254         if (!W_ERROR_IS_OK(result)) {
7255                 return result;
7256         }
7257
7258         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7259                                                      spoolss_EnumPrinterDrivers, 
7260                                                      *r->out.info, r->in.level,
7261                                                      *r->out.count);
7262         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7263         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7264
7265         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7266 }
7267
7268 /****************************************************************
7269  _spoolss_EnumForms
7270 ****************************************************************/
7271
7272 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7273                           struct spoolss_EnumForms *r)
7274 {
7275         WERROR result;
7276
7277         *r->out.count = 0;
7278         *r->out.needed = 0;
7279         *r->out.info = NULL;
7280
7281         /* that's an [in out] buffer */
7282
7283         if (!r->in.buffer && (r->in.offered != 0) ) {
7284                 return WERR_INVALID_PARAM;
7285         }
7286
7287         DEBUG(4,("_spoolss_EnumForms\n"));
7288         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7289         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7290
7291         switch (r->in.level) {
7292         case 1:
7293                 result = winreg_printer_enumforms1(p->mem_ctx,
7294                                                    get_server_info_system(),
7295                                                    p->msg_ctx,
7296                                                    r->out.count,
7297                                                    r->out.info);
7298                 break;
7299         default:
7300                 result = WERR_UNKNOWN_LEVEL;
7301                 break;
7302         }
7303
7304         if (!W_ERROR_IS_OK(result)) {
7305                 return result;
7306         }
7307
7308         if (*r->out.count == 0) {
7309                 return WERR_NO_MORE_ITEMS;
7310         }
7311
7312         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7313                                                      spoolss_EnumForms, 
7314                                                      *r->out.info, r->in.level,
7315                                                      *r->out.count);
7316         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7317         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7318
7319         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7320 }
7321
7322 /****************************************************************
7323  _spoolss_GetForm
7324 ****************************************************************/
7325
7326 WERROR _spoolss_GetForm(struct pipes_struct *p,
7327                         struct spoolss_GetForm *r)
7328 {
7329         WERROR result;
7330
7331         /* that's an [in out] buffer */
7332
7333         if (!r->in.buffer && (r->in.offered != 0)) {
7334                 return WERR_INVALID_PARAM;
7335         }
7336
7337         DEBUG(4,("_spoolss_GetForm\n"));
7338         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7339         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7340
7341         switch (r->in.level) {
7342         case 1:
7343                 result = winreg_printer_getform1(p->mem_ctx,
7344                                                  get_server_info_system(),
7345                                                  p->msg_ctx,
7346                                                  r->in.form_name,
7347                                                  &r->out.info->info1);
7348                 break;
7349         default:
7350                 result = WERR_UNKNOWN_LEVEL;
7351                 break;
7352         }
7353
7354         if (!W_ERROR_IS_OK(result)) {
7355                 TALLOC_FREE(r->out.info);
7356                 return result;
7357         }
7358
7359         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo, 
7360                                                r->out.info, r->in.level);
7361         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7362
7363         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7364 }
7365
7366 /****************************************************************************
7367 ****************************************************************************/
7368
7369 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7370                           struct spoolss_PortInfo1 *r,
7371                           const char *name)
7372 {
7373         r->port_name = talloc_strdup(mem_ctx, name);
7374         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7375
7376         return WERR_OK;
7377 }
7378
7379 /****************************************************************************
7380  TODO: This probably needs distinguish between TCP/IP and Local ports
7381  somehow.
7382 ****************************************************************************/
7383
7384 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7385                           struct spoolss_PortInfo2 *r,
7386                           const char *name)
7387 {
7388         r->port_name = talloc_strdup(mem_ctx, name);
7389         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7390
7391         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7392         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7393
7394         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7395         W_ERROR_HAVE_NO_MEMORY(r->description);
7396
7397         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7398         r->reserved = 0;
7399
7400         return WERR_OK;
7401 }
7402
7403
7404 /****************************************************************************
7405  wrapper around the enumer ports command
7406 ****************************************************************************/
7407
7408 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7409 {
7410         char *cmd = lp_enumports_cmd();
7411         char **qlines = NULL;
7412         char *command = NULL;
7413         int numlines;
7414         int ret;
7415         int fd;
7416
7417         *count = 0;
7418         *lines = NULL;
7419
7420         /* if no hook then just fill in the default port */
7421
7422         if ( !*cmd ) {
7423                 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7424                         return WERR_NOMEM;
7425                 }
7426                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7427                         TALLOC_FREE(qlines);
7428                         return WERR_NOMEM;
7429                 }
7430                 qlines[1] = NULL;
7431                 numlines = 1;
7432         }
7433         else {
7434                 /* we have a valid enumport command */
7435
7436                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7437                 if (!command) {
7438                         return WERR_NOMEM;
7439                 }
7440
7441                 DEBUG(10,("Running [%s]\n", command));
7442                 ret = smbrun(command, &fd);
7443                 DEBUG(10,("Returned [%d]\n", ret));
7444                 TALLOC_FREE(command);
7445                 if (ret != 0) {
7446                         if (fd != -1) {
7447                                 close(fd);
7448                         }
7449                         return WERR_ACCESS_DENIED;
7450                 }
7451
7452                 numlines = 0;
7453                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7454                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7455                 close(fd);
7456         }
7457
7458         *count = numlines;
7459         *lines = qlines;
7460
7461         return WERR_OK;
7462 }
7463
7464 /****************************************************************************
7465  enumports level 1.
7466 ****************************************************************************/
7467
7468 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7469                                 union spoolss_PortInfo **info_p,
7470                                 uint32_t *count)
7471 {
7472         union spoolss_PortInfo *info = NULL;
7473         int i=0;
7474         WERROR result = WERR_OK;
7475         char **qlines = NULL;
7476         int numlines = 0;
7477
7478         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7479         if (!W_ERROR_IS_OK(result)) {
7480                 goto out;
7481         }
7482
7483         if (numlines) {
7484                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7485                 if (!info) {
7486                         DEBUG(10,("Returning WERR_NOMEM\n"));
7487                         result = WERR_NOMEM;
7488                         goto out;
7489                 }
7490
7491                 for (i=0; i<numlines; i++) {
7492                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7493                         result = fill_port_1(info, &info[i].info1, qlines[i]);
7494                         if (!W_ERROR_IS_OK(result)) {
7495                                 goto out;
7496                         }
7497                 }
7498         }
7499         TALLOC_FREE(qlines);
7500
7501 out:
7502         if (!W_ERROR_IS_OK(result)) {
7503                 TALLOC_FREE(info);
7504                 TALLOC_FREE(qlines);
7505                 *count = 0;
7506                 *info_p = NULL;
7507                 return result;
7508         }
7509
7510         *info_p = info;
7511         *count = numlines;
7512
7513         return WERR_OK;
7514 }
7515
7516 /****************************************************************************
7517  enumports level 2.
7518 ****************************************************************************/
7519
7520 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7521                                 union spoolss_PortInfo **info_p,
7522                                 uint32_t *count)
7523 {
7524         union spoolss_PortInfo *info = NULL;
7525         int i=0;
7526         WERROR result = WERR_OK;
7527         char **qlines = NULL;
7528         int numlines = 0;
7529
7530         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7531         if (!W_ERROR_IS_OK(result)) {
7532                 goto out;
7533         }
7534
7535         if (numlines) {
7536                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7537                 if (!info) {
7538                         DEBUG(10,("Returning WERR_NOMEM\n"));
7539                         result = WERR_NOMEM;
7540                         goto out;
7541                 }
7542
7543                 for (i=0; i<numlines; i++) {
7544                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7545                         result = fill_port_2(info, &info[i].info2, qlines[i]);
7546                         if (!W_ERROR_IS_OK(result)) {
7547                                 goto out;
7548                         }
7549                 }
7550         }
7551         TALLOC_FREE(qlines);
7552
7553 out:
7554         if (!W_ERROR_IS_OK(result)) {
7555                 TALLOC_FREE(info);
7556                 TALLOC_FREE(qlines);
7557                 *count = 0;
7558                 *info_p = NULL;
7559                 return result;
7560         }
7561
7562         *info_p = info;
7563         *count = numlines;
7564
7565         return WERR_OK;
7566 }
7567
7568 /****************************************************************
7569  _spoolss_EnumPorts
7570 ****************************************************************/
7571
7572 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
7573                           struct spoolss_EnumPorts *r)
7574 {
7575         WERROR result;
7576
7577         /* that's an [in out] buffer */
7578
7579         if (!r->in.buffer && (r->in.offered != 0)) {
7580                 return WERR_INVALID_PARAM;
7581         }
7582
7583         DEBUG(4,("_spoolss_EnumPorts\n"));
7584
7585         *r->out.count = 0;
7586         *r->out.needed = 0;
7587         *r->out.info = NULL;
7588
7589         switch (r->in.level) {
7590         case 1:
7591                 result = enumports_level_1(p->mem_ctx, r->out.info,
7592                                            r->out.count);
7593                 break;
7594         case 2:
7595                 result = enumports_level_2(p->mem_ctx, r->out.info,
7596                                            r->out.count);
7597                 break;
7598         default:
7599                 return WERR_UNKNOWN_LEVEL;
7600         }
7601
7602         if (!W_ERROR_IS_OK(result)) {
7603                 return result;
7604         }
7605
7606         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7607                                                      spoolss_EnumPorts, 
7608                                                      *r->out.info, r->in.level,
7609                                                      *r->out.count);
7610         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7611         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7612
7613         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7614 }
7615
7616 /****************************************************************************
7617 ****************************************************************************/
7618
7619 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
7620                                            const char *server,
7621                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
7622                                            struct spoolss_DeviceMode *devmode,
7623                                            struct security_descriptor *secdesc,
7624                                            struct spoolss_UserLevelCtr *user_ctr,
7625                                            struct policy_handle *handle)
7626 {
7627         struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
7628         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
7629         int     snum;
7630         WERROR err = WERR_OK;
7631
7632         /* samba does not have a concept of local, non-shared printers yet, so
7633          * make sure we always setup sharename - gd */
7634         if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
7635             (info2->printername != NULL && info2->printername[0] != '\0')) {
7636                 DEBUG(5, ("spoolss_addprinterex_level_2: "
7637                         "no sharename has been set, setting printername %s as sharename\n",
7638                         info2->printername));
7639                 info2->sharename = info2->printername;
7640         }
7641
7642         /* check to see if the printer already exists */
7643         if ((snum = print_queue_snum(info2->sharename)) != -1) {
7644                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7645                         info2->sharename));
7646                 return WERR_PRINTER_ALREADY_EXISTS;
7647         }
7648
7649         if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7650                 if ((snum = print_queue_snum(info2->printername)) != -1) {
7651                         DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7652                                 info2->printername));
7653                         return WERR_PRINTER_ALREADY_EXISTS;
7654                 }
7655         }
7656
7657         /* validate printer info struct */
7658         if (!info2->printername || strlen(info2->printername) == 0) {
7659                 return WERR_INVALID_PRINTER_NAME;
7660         }
7661         if (!info2->portname || strlen(info2->portname) == 0) {
7662                 return WERR_UNKNOWN_PORT;
7663         }
7664         if (!info2->drivername || strlen(info2->drivername) == 0) {
7665                 return WERR_UNKNOWN_PRINTER_DRIVER;
7666         }
7667         if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
7668                 return WERR_UNKNOWN_PRINTPROCESSOR;
7669         }
7670
7671         /* FIXME!!!  smbd should check to see if the driver is installed before
7672            trying to add a printer like this  --jerry */
7673
7674         if (*lp_addprinter_cmd() ) {
7675                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7676                                        info2, p->client_id->addr,
7677                                        p->msg_ctx) ) {
7678                         return WERR_ACCESS_DENIED;
7679                 }
7680         } else {
7681                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7682                         "smb.conf parameter \"addprinter command\" is defined. This"
7683                         "parameter must exist for this call to succeed\n",
7684                         info2->sharename ));
7685         }
7686
7687         if ((snum = print_queue_snum(info2->sharename)) == -1) {
7688                 return WERR_ACCESS_DENIED;
7689         }
7690
7691         /* you must be a printer admin to add a new printer */
7692         if (!print_access_check(get_server_info_system(),
7693                                 p->msg_ctx,
7694                                 snum,
7695                                 PRINTER_ACCESS_ADMINISTER)) {
7696                 return WERR_ACCESS_DENIED;
7697         }
7698
7699         /*
7700          * Do sanity check on the requested changes for Samba.
7701          */
7702
7703         if (!check_printer_ok(p->mem_ctx, info2, snum)) {
7704                 return WERR_INVALID_PARAM;
7705         }
7706
7707         if (devmode == NULL) {
7708                 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
7709         }
7710
7711         update_dsspooler(p->mem_ctx,
7712                          get_server_info_system(),
7713                          p->msg_ctx,
7714                          0,
7715                          info2,
7716                          NULL);
7717
7718         err = winreg_update_printer(p->mem_ctx,
7719                                     get_server_info_system(),
7720                                     p->msg_ctx,
7721                                     info2->sharename,
7722                                     info2_mask,
7723                                     info2,
7724                                     devmode,
7725                                     secdesc);
7726         if (!W_ERROR_IS_OK(err)) {
7727                 return err;
7728         }
7729
7730         if (!open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER)) {
7731                 /* Handle open failed - remove addition. */
7732                 ZERO_STRUCTP(handle);
7733                 return WERR_ACCESS_DENIED;
7734         }
7735
7736         return WERR_OK;
7737 }
7738
7739 /****************************************************************
7740  _spoolss_AddPrinterEx
7741 ****************************************************************/
7742
7743 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
7744                              struct spoolss_AddPrinterEx *r)
7745 {
7746         switch (r->in.info_ctr->level) {
7747         case 1:
7748                 /* we don't handle yet */
7749                 /* but I know what to do ... */
7750                 return WERR_UNKNOWN_LEVEL;
7751         case 2:
7752                 return spoolss_addprinterex_level_2(p, r->in.server,
7753                                                     r->in.info_ctr,
7754                                                     r->in.devmode_ctr->devmode,
7755                                                     r->in.secdesc_ctr->sd,
7756                                                     r->in.userlevel_ctr,
7757                                                     r->out.handle);
7758         default:
7759                 return WERR_UNKNOWN_LEVEL;
7760         }
7761 }
7762
7763 /****************************************************************
7764  _spoolss_AddPrinter
7765 ****************************************************************/
7766
7767 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
7768                            struct spoolss_AddPrinter *r)
7769 {
7770         struct spoolss_AddPrinterEx a;
7771         struct spoolss_UserLevelCtr userlevel_ctr;
7772
7773         ZERO_STRUCT(userlevel_ctr);
7774
7775         userlevel_ctr.level = 1;
7776
7777         a.in.server             = r->in.server;
7778         a.in.info_ctr           = r->in.info_ctr;
7779         a.in.devmode_ctr        = r->in.devmode_ctr;
7780         a.in.secdesc_ctr        = r->in.secdesc_ctr;
7781         a.in.userlevel_ctr      = &userlevel_ctr;
7782         a.out.handle            = r->out.handle;
7783
7784         return _spoolss_AddPrinterEx(p, &a);
7785 }
7786
7787 /****************************************************************
7788  _spoolss_AddPrinterDriverEx
7789 ****************************************************************/
7790
7791 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
7792                                    struct spoolss_AddPrinterDriverEx *r)
7793 {
7794         WERROR err = WERR_OK;
7795         const char *driver_name = NULL;
7796         uint32_t version;
7797         const char *fn;
7798
7799         switch (p->opnum) {
7800                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7801                         fn = "_spoolss_AddPrinterDriver";
7802                         break;
7803                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7804                         fn = "_spoolss_AddPrinterDriverEx";
7805                         break;
7806                 default:
7807                         return WERR_INVALID_PARAM;
7808         }
7809
7810         /*
7811          * we only support the semantics of AddPrinterDriver()
7812          * i.e. only copy files that are newer than existing ones
7813          */
7814
7815         if (r->in.flags == 0) {
7816                 return WERR_INVALID_PARAM;
7817         }
7818
7819         if (r->in.flags != APD_COPY_NEW_FILES) {
7820                 return WERR_ACCESS_DENIED;
7821         }
7822
7823         /* FIXME */
7824         if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
7825                 /* Clever hack from Martin Zielinski <mz@seh.de>
7826                  * to allow downgrade from level 8 (Vista).
7827                  */
7828                 DEBUG(0,("%s: level %d not yet implemented\n", fn,
7829                         r->in.info_ctr->level));
7830                 return WERR_UNKNOWN_LEVEL;
7831         }
7832
7833         DEBUG(5,("Cleaning driver's information\n"));
7834         err = clean_up_driver_struct(p->mem_ctx, p, r->in.info_ctr);
7835         if (!W_ERROR_IS_OK(err))
7836                 goto done;
7837
7838         DEBUG(5,("Moving driver to final destination\n"));
7839         if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, r->in.info_ctr,
7840                                                               &err)) ) {
7841                 goto done;
7842         }
7843
7844         err = winreg_add_driver(p->mem_ctx,
7845                                 get_server_info_system(),
7846                                 p->msg_ctx,
7847                                 r->in.info_ctr,
7848                                 &driver_name,
7849                                 &version);
7850         if (!W_ERROR_IS_OK(err)) {
7851                 goto done;
7852         }
7853
7854         /*
7855          * I think this is where he DrvUpgradePrinter() hook would be
7856          * be called in a driver's interface DLL on a Windows NT 4.0/2k
7857          * server.  Right now, we just need to send ourselves a message
7858          * to update each printer bound to this driver.   --jerry
7859          */
7860
7861         if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
7862                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7863                         fn, driver_name));
7864         }
7865
7866 done:
7867         return err;
7868 }
7869
7870 /****************************************************************
7871  _spoolss_AddPrinterDriver
7872 ****************************************************************/
7873
7874 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
7875                                  struct spoolss_AddPrinterDriver *r)
7876 {
7877         struct spoolss_AddPrinterDriverEx a;
7878
7879         switch (r->in.info_ctr->level) {
7880         case 2:
7881         case 3:
7882         case 4:
7883         case 5:
7884                 break;
7885         default:
7886                 return WERR_UNKNOWN_LEVEL;
7887         }
7888
7889         a.in.servername         = r->in.servername;
7890         a.in.info_ctr           = r->in.info_ctr;
7891         a.in.flags              = APD_COPY_NEW_FILES;
7892
7893         return _spoolss_AddPrinterDriverEx(p, &a);
7894 }
7895
7896 /****************************************************************************
7897 ****************************************************************************/
7898
7899 struct _spoolss_paths {
7900         int type;
7901         const char *share;
7902         const char *dir;
7903 };
7904
7905 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
7906
7907 static const struct _spoolss_paths spoolss_paths[]= {
7908         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
7909         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
7910 };
7911
7912 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
7913                                           const char *servername,
7914                                           const char *environment,
7915                                           int component,
7916                                           char **path)
7917 {
7918         const char *pservername = NULL;
7919         const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
7920         const char *short_archi;
7921
7922         *path = NULL;
7923
7924         /* environment may be empty */
7925         if (environment && strlen(environment)) {
7926                 long_archi = environment;
7927         }
7928
7929         /* servername may be empty */
7930         if (servername && strlen(servername)) {
7931                 pservername = canon_servername(servername);
7932
7933                 if (!is_myname_or_ipaddr(pservername)) {
7934                         return WERR_INVALID_PARAM;
7935                 }
7936         }
7937
7938         if (!(short_archi = get_short_archi(long_archi))) {
7939                 return WERR_INVALID_ENVIRONMENT;
7940         }
7941
7942         switch (component) {
7943         case SPOOLSS_PRTPROCS_PATH:
7944         case SPOOLSS_DRIVER_PATH:
7945                 if (pservername) {
7946                         *path = talloc_asprintf(mem_ctx,
7947                                         "\\\\%s\\%s\\%s",
7948                                         pservername,
7949                                         spoolss_paths[component].share,
7950                                         short_archi);
7951                 } else {
7952                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
7953                                         SPOOLSS_DEFAULT_SERVER_PATH,
7954                                         spoolss_paths[component].dir,
7955                                         short_archi);
7956                 }
7957                 break;
7958         default:
7959                 return WERR_INVALID_PARAM;
7960         }
7961
7962         if (!*path) {
7963                 return WERR_NOMEM;
7964         }
7965
7966         return WERR_OK;
7967 }
7968
7969 /****************************************************************************
7970 ****************************************************************************/
7971
7972 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
7973                                           const char *servername,
7974                                           const char *environment,
7975                                           struct spoolss_DriverDirectoryInfo1 *r)
7976 {
7977         WERROR werr;
7978         char *path = NULL;
7979
7980         werr = compose_spoolss_server_path(mem_ctx,
7981                                            servername,
7982                                            environment,
7983                                            SPOOLSS_DRIVER_PATH,
7984                                            &path);
7985         if (!W_ERROR_IS_OK(werr)) {
7986                 return werr;
7987         }
7988
7989         DEBUG(4,("printer driver directory: [%s]\n", path));
7990
7991         r->directory_name = path;
7992
7993         return WERR_OK;
7994 }
7995
7996 /****************************************************************
7997  _spoolss_GetPrinterDriverDirectory
7998 ****************************************************************/
7999
8000 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8001                                           struct spoolss_GetPrinterDriverDirectory *r)
8002 {
8003         WERROR werror;
8004
8005         /* that's an [in out] buffer */
8006
8007         if (!r->in.buffer && (r->in.offered != 0)) {
8008                 return WERR_INVALID_PARAM;
8009         }
8010
8011         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8012                 r->in.level));
8013
8014         *r->out.needed = 0;
8015
8016         /* r->in.level is ignored */
8017
8018         werror = getprinterdriverdir_level_1(p->mem_ctx,
8019                                              r->in.server,
8020                                              r->in.environment,
8021                                              &r->out.info->info1);
8022         if (!W_ERROR_IS_OK(werror)) {
8023                 TALLOC_FREE(r->out.info);
8024                 return werror;
8025         }
8026
8027         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo, 
8028                                                r->out.info, r->in.level);
8029         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8030
8031         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8032 }
8033
8034 /****************************************************************
8035  _spoolss_EnumPrinterData
8036 ****************************************************************/
8037
8038 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8039                                 struct spoolss_EnumPrinterData *r)
8040 {
8041         WERROR result;
8042         struct spoolss_EnumPrinterDataEx r2;
8043         uint32_t count;
8044         struct spoolss_PrinterEnumValues *info, *val = NULL;
8045         uint32_t needed;
8046
8047         r2.in.handle    = r->in.handle;
8048         r2.in.key_name  = "PrinterDriverData";
8049         r2.in.offered   = 0;
8050         r2.out.count    = &count;
8051         r2.out.info     = &info;
8052         r2.out.needed   = &needed;
8053
8054         result = _spoolss_EnumPrinterDataEx(p, &r2);
8055         if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8056                 r2.in.offered = needed;
8057                 result = _spoolss_EnumPrinterDataEx(p, &r2);
8058         }
8059         if (!W_ERROR_IS_OK(result)) {
8060                 return result;
8061         }
8062
8063         /*
8064          * The NT machine wants to know the biggest size of value and data
8065          *
8066          * cf: MSDN EnumPrinterData remark section
8067          */
8068
8069         if (!r->in.value_offered && !r->in.data_offered) {
8070                 uint32_t biggest_valuesize = 0;
8071                 uint32_t biggest_datasize = 0;
8072                 int i, name_length;
8073
8074                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8075
8076                 for (i=0; i<count; i++) {
8077
8078                         name_length = strlen(info[i].value_name);
8079                         if (strlen(info[i].value_name) > biggest_valuesize) {
8080                                 biggest_valuesize = name_length;
8081                         }
8082
8083                         if (info[i].data_length > biggest_datasize) {
8084                                 biggest_datasize = info[i].data_length;
8085                         }
8086
8087                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8088                                 biggest_datasize));
8089                 }
8090
8091                 /* the value is an UNICODE string but real_value_size is the length
8092                    in bytes including the trailing 0 */
8093
8094                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8095                 *r->out.data_needed  = biggest_datasize;
8096
8097                 DEBUG(6,("final values: [%d], [%d]\n",
8098                         *r->out.value_needed, *r->out.data_needed));
8099
8100                 return WERR_OK;
8101         }
8102
8103         if (r->in.enum_index < count) {
8104                 val = &info[r->in.enum_index];
8105         }
8106
8107         if (val == NULL) {
8108                 /* out_value should default to "" or else NT4 has
8109                    problems unmarshalling the response */
8110
8111                 if (r->in.value_offered) {
8112                         *r->out.value_needed = 1;
8113                         r->out.value_name = talloc_strdup(r, "");
8114                         if (!r->out.value_name) {
8115                                 return WERR_NOMEM;
8116                         }
8117                 } else {
8118                         r->out.value_name = NULL;
8119                         *r->out.value_needed = 0;
8120                 }
8121
8122                 /* the data is counted in bytes */
8123
8124                 *r->out.data_needed = r->in.data_offered;
8125
8126                 result = WERR_NO_MORE_ITEMS;
8127         } else {
8128                 /*
8129                  * the value is:
8130                  * - counted in bytes in the request
8131                  * - counted in UNICODE chars in the max reply
8132                  * - counted in bytes in the real size
8133                  *
8134                  * take a pause *before* coding not *during* coding
8135                  */
8136
8137                 /* name */
8138                 if (r->in.value_offered) {
8139                         r->out.value_name = talloc_strdup(r, val->value_name);
8140                         if (!r->out.value_name) {
8141                                 return WERR_NOMEM;
8142                         }
8143                         *r->out.value_needed = val->value_name_len;
8144                 } else {
8145                         r->out.value_name = NULL;
8146                         *r->out.value_needed = 0;
8147                 }
8148
8149                 /* type */
8150
8151                 *r->out.type = val->type;
8152
8153                 /* data - counted in bytes */
8154
8155                 /*
8156                  * See the section "Dynamically Typed Query Parameters"
8157                  * in MS-RPRN.
8158                  */
8159
8160                 if (r->out.data && val->data && val->data->data &&
8161                                 val->data_length && r->in.data_offered) {
8162                         memcpy(r->out.data, val->data->data,
8163                                 MIN(val->data_length,r->in.data_offered));
8164                 }
8165
8166                 *r->out.data_needed = val->data_length;
8167
8168                 result = WERR_OK;
8169         }
8170
8171         return result;
8172 }
8173
8174 /****************************************************************
8175  _spoolss_SetPrinterData
8176 ****************************************************************/
8177
8178 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8179                                struct spoolss_SetPrinterData *r)
8180 {
8181         struct spoolss_SetPrinterDataEx r2;
8182
8183         r2.in.handle            = r->in.handle;
8184         r2.in.key_name          = "PrinterDriverData";
8185         r2.in.value_name        = r->in.value_name;
8186         r2.in.type              = r->in.type;
8187         r2.in.data              = r->in.data;
8188         r2.in.offered           = r->in.offered;
8189
8190         return _spoolss_SetPrinterDataEx(p, &r2);
8191 }
8192
8193 /****************************************************************
8194  _spoolss_ResetPrinter
8195 ****************************************************************/
8196
8197 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8198                              struct spoolss_ResetPrinter *r)
8199 {
8200         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8201         int             snum;
8202
8203         DEBUG(5,("_spoolss_ResetPrinter\n"));
8204
8205         /*
8206          * All we do is to check to see if the handle and queue is valid.
8207          * This call really doesn't mean anything to us because we only
8208          * support RAW printing.   --jerry
8209          */
8210
8211         if (!Printer) {
8212                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8213                         OUR_HANDLE(r->in.handle)));
8214                 return WERR_BADFID;
8215         }
8216
8217         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8218                 return WERR_BADFID;
8219
8220
8221         /* blindly return success */
8222         return WERR_OK;
8223 }
8224
8225 /****************************************************************
8226  _spoolss_DeletePrinterData
8227 ****************************************************************/
8228
8229 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8230                                   struct spoolss_DeletePrinterData *r)
8231 {
8232         struct spoolss_DeletePrinterDataEx r2;
8233
8234         r2.in.handle            = r->in.handle;
8235         r2.in.key_name          = "PrinterDriverData";
8236         r2.in.value_name        = r->in.value_name;
8237
8238         return _spoolss_DeletePrinterDataEx(p, &r2);
8239 }
8240
8241 /****************************************************************
8242  _spoolss_AddForm
8243 ****************************************************************/
8244
8245 WERROR _spoolss_AddForm(struct pipes_struct *p,
8246                         struct spoolss_AddForm *r)
8247 {
8248         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8249         int snum = -1;
8250         WERROR status = WERR_OK;
8251         uint64_t se_printop = SE_PRINT_OPERATOR;
8252
8253         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8254
8255         DEBUG(5,("_spoolss_AddForm\n"));
8256
8257         if (!Printer) {
8258                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8259                         OUR_HANDLE(r->in.handle)));
8260                 return WERR_BADFID;
8261         }
8262
8263         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8264            and not a printer admin, then fail */
8265
8266         if ((p->server_info->utok.uid != sec_initial_uid()) &&
8267              !user_has_privileges(p->server_info->ptok, &se_printop) &&
8268              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8269                                           p->server_info->info3->base.domain.string,
8270                                           NULL,
8271                                           p->server_info->ptok,
8272                                           lp_printer_admin(snum))) {
8273                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8274                 return WERR_ACCESS_DENIED;
8275         }
8276
8277         switch (form->flags) {
8278         case SPOOLSS_FORM_USER:
8279         case SPOOLSS_FORM_BUILTIN:
8280         case SPOOLSS_FORM_PRINTER:
8281                 break;
8282         default:
8283                 return WERR_INVALID_PARAM;
8284         }
8285
8286         status = winreg_printer_addform1(p->mem_ctx,
8287                                          get_server_info_system(),
8288                                          p->msg_ctx,
8289                                          form);
8290         if (!W_ERROR_IS_OK(status)) {
8291                 return status;
8292         }
8293
8294         /*
8295          * ChangeID must always be set if this is a printer
8296          */
8297         if (Printer->printer_type == SPLHND_PRINTER) {
8298                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8299                         return WERR_BADFID;
8300                 }
8301
8302                 status = winreg_printer_update_changeid(p->mem_ctx,
8303                                                         get_server_info_system(),
8304                                                         p->msg_ctx,
8305                                                         lp_const_servicename(snum));
8306                 if (!W_ERROR_IS_OK(status)) {
8307                         return status;
8308                 }
8309         }
8310
8311         return status;
8312 }
8313
8314 /****************************************************************
8315  _spoolss_DeleteForm
8316 ****************************************************************/
8317
8318 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8319                            struct spoolss_DeleteForm *r)
8320 {
8321         const char *form_name = r->in.form_name;
8322         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8323         int snum = -1;
8324         WERROR status = WERR_OK;
8325         uint64_t se_printop = SE_PRINT_OPERATOR;
8326
8327         DEBUG(5,("_spoolss_DeleteForm\n"));
8328
8329         if (!Printer) {
8330                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8331                         OUR_HANDLE(r->in.handle)));
8332                 return WERR_BADFID;
8333         }
8334
8335         if ((p->server_info->utok.uid != sec_initial_uid()) &&
8336              !user_has_privileges(p->server_info->ptok, &se_printop) &&
8337              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8338                                           p->server_info->info3->base.domain.string,
8339                                           NULL,
8340                                           p->server_info->ptok,
8341                                           lp_printer_admin(snum))) {
8342                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8343                 return WERR_ACCESS_DENIED;
8344         }
8345
8346         status = winreg_printer_deleteform1(p->mem_ctx,
8347                                             get_server_info_system(),
8348                                             p->msg_ctx,
8349                                             form_name);
8350         if (!W_ERROR_IS_OK(status)) {
8351                 return status;
8352         }
8353
8354         /*
8355          * ChangeID must always be set if this is a printer
8356          */
8357         if (Printer->printer_type == SPLHND_PRINTER) {
8358                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8359                         return WERR_BADFID;
8360                 }
8361
8362                 status = winreg_printer_update_changeid(p->mem_ctx,
8363                                                         get_server_info_system(),
8364                                                         p->msg_ctx,
8365                                                         lp_const_servicename(snum));
8366                 if (!W_ERROR_IS_OK(status)) {
8367                         return status;
8368                 }
8369         }
8370
8371         return status;
8372 }
8373
8374 /****************************************************************
8375  _spoolss_SetForm
8376 ****************************************************************/
8377
8378 WERROR _spoolss_SetForm(struct pipes_struct *p,
8379                         struct spoolss_SetForm *r)
8380 {
8381         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8382         const char *form_name = r->in.form_name;
8383         int snum = -1;
8384         WERROR status = WERR_OK;
8385         uint64_t se_printop = SE_PRINT_OPERATOR;
8386
8387         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8388
8389         DEBUG(5,("_spoolss_SetForm\n"));
8390
8391         if (!Printer) {
8392                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8393                         OUR_HANDLE(r->in.handle)));
8394                 return WERR_BADFID;
8395         }
8396
8397         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8398            and not a printer admin, then fail */
8399
8400         if ((p->server_info->utok.uid != sec_initial_uid()) &&
8401              !user_has_privileges(p->server_info->ptok, &se_printop) &&
8402              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8403                                           p->server_info->info3->base.domain.string,
8404                                           NULL,
8405                                           p->server_info->ptok,
8406                                           lp_printer_admin(snum))) {
8407                 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8408                 return WERR_ACCESS_DENIED;
8409         }
8410
8411         status = winreg_printer_setform1(p->mem_ctx,
8412                                          get_server_info_system(),
8413                                          p->msg_ctx,
8414                                          form_name,
8415                                          form);
8416         if (!W_ERROR_IS_OK(status)) {
8417                 return status;
8418         }
8419
8420         /*
8421          * ChangeID must always be set if this is a printer
8422          */
8423         if (Printer->printer_type == SPLHND_PRINTER) {
8424                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8425                         return WERR_BADFID;
8426                 }
8427
8428                 status = winreg_printer_update_changeid(p->mem_ctx,
8429                                                         get_server_info_system(),
8430                                                         p->msg_ctx,
8431                                                         lp_const_servicename(snum));
8432                 if (!W_ERROR_IS_OK(status)) {
8433                         return status;
8434                 }
8435         }
8436
8437         return status;
8438 }
8439
8440 /****************************************************************************
8441  fill_print_processor1
8442 ****************************************************************************/
8443
8444 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8445                                     struct spoolss_PrintProcessorInfo1 *r,
8446                                     const char *print_processor_name)
8447 {
8448         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8449         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8450
8451         return WERR_OK;
8452 }
8453
8454 /****************************************************************************
8455  enumprintprocessors level 1.
8456 ****************************************************************************/
8457
8458 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8459                                           union spoolss_PrintProcessorInfo **info_p,
8460                                           uint32_t *count)
8461 {
8462         union spoolss_PrintProcessorInfo *info;
8463         WERROR result;
8464
8465         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8466         W_ERROR_HAVE_NO_MEMORY(info);
8467
8468         *count = 1;
8469
8470         result = fill_print_processor1(info, &info[0].info1, "winprint");
8471         if (!W_ERROR_IS_OK(result)) {
8472                 goto out;
8473         }
8474
8475  out:
8476         if (!W_ERROR_IS_OK(result)) {
8477                 TALLOC_FREE(info);
8478                 *count = 0;
8479                 return result;
8480         }
8481
8482         *info_p = info;
8483
8484         return WERR_OK;
8485 }
8486
8487 /****************************************************************
8488  _spoolss_EnumPrintProcessors
8489 ****************************************************************/
8490
8491 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
8492                                     struct spoolss_EnumPrintProcessors *r)
8493 {
8494         WERROR result;
8495
8496         /* that's an [in out] buffer */
8497
8498         if (!r->in.buffer && (r->in.offered != 0)) {
8499                 return WERR_INVALID_PARAM;
8500         }
8501
8502         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8503
8504         /*
8505          * Enumerate the print processors ...
8506          *
8507          * Just reply with "winprint", to keep NT happy
8508          * and I can use my nice printer checker.
8509          */
8510
8511         *r->out.count = 0;
8512         *r->out.needed = 0;
8513         *r->out.info = NULL;
8514
8515         switch (r->in.level) {
8516         case 1:
8517                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8518                                                      r->out.count);
8519                 break;
8520         default:
8521                 return WERR_UNKNOWN_LEVEL;
8522         }
8523
8524         if (!W_ERROR_IS_OK(result)) {
8525                 return result;
8526         }
8527
8528         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8529                                                      spoolss_EnumPrintProcessors,
8530                                                      *r->out.info, r->in.level,
8531                                                      *r->out.count);
8532         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8533         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8534
8535         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8536 }
8537
8538 /****************************************************************************
8539  fill_printprocdatatype1
8540 ****************************************************************************/
8541
8542 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8543                                       struct spoolss_PrintProcDataTypesInfo1 *r,
8544                                       const char *name_array)
8545 {
8546         r->name_array = talloc_strdup(mem_ctx, name_array);
8547         W_ERROR_HAVE_NO_MEMORY(r->name_array);
8548
8549         return WERR_OK;
8550 }
8551
8552 /****************************************************************************
8553  enumprintprocdatatypes level 1.
8554 ****************************************************************************/
8555
8556 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8557                                              union spoolss_PrintProcDataTypesInfo **info_p,
8558                                              uint32_t *count)
8559 {
8560         WERROR result;
8561         union spoolss_PrintProcDataTypesInfo *info;
8562
8563         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8564         W_ERROR_HAVE_NO_MEMORY(info);
8565
8566         *count = 1;
8567
8568         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8569         if (!W_ERROR_IS_OK(result)) {
8570                 goto out;
8571         }
8572
8573  out:
8574         if (!W_ERROR_IS_OK(result)) {
8575                 TALLOC_FREE(info);
8576                 *count = 0;
8577                 return result;
8578         }
8579
8580         *info_p = info;
8581
8582         return WERR_OK;
8583 }
8584
8585 /****************************************************************
8586  _spoolss_EnumPrintProcDataTypes
8587 ****************************************************************/
8588
8589 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
8590                                        struct spoolss_EnumPrintProcDataTypes *r)
8591 {
8592         WERROR result;
8593
8594         /* that's an [in out] buffer */
8595
8596         if (!r->in.buffer && (r->in.offered != 0)) {
8597                 return WERR_INVALID_PARAM;
8598         }
8599
8600         DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8601
8602         *r->out.count = 0;
8603         *r->out.needed = 0;
8604         *r->out.info = NULL;
8605
8606         switch (r->in.level) {
8607         case 1:
8608                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8609                                                         r->out.count);
8610                 break;
8611         default:
8612                 return WERR_UNKNOWN_LEVEL;
8613         }
8614
8615         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8616                                                      spoolss_EnumPrintProcDataTypes, 
8617                                                      *r->out.info, r->in.level,
8618                                                      *r->out.count);
8619         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8620         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8621
8622         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8623 }
8624
8625 /****************************************************************************
8626  fill_monitor_1
8627 ****************************************************************************/
8628
8629 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8630                              struct spoolss_MonitorInfo1 *r,
8631                              const char *monitor_name)
8632 {
8633         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8634         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8635
8636         return WERR_OK;
8637 }
8638
8639 /****************************************************************************
8640  fill_monitor_2
8641 ****************************************************************************/
8642
8643 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8644                              struct spoolss_MonitorInfo2 *r,
8645                              const char *monitor_name,
8646                              const char *environment,
8647                              const char *dll_name)
8648 {
8649         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8650         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8651         r->environment                  = talloc_strdup(mem_ctx, environment);
8652         W_ERROR_HAVE_NO_MEMORY(r->environment);
8653         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
8654         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8655
8656         return WERR_OK;
8657 }
8658
8659 /****************************************************************************
8660  enumprintmonitors level 1.
8661 ****************************************************************************/
8662
8663 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8664                                         union spoolss_MonitorInfo **info_p,
8665                                         uint32_t *count)
8666 {
8667         union spoolss_MonitorInfo *info;
8668         WERROR result = WERR_OK;
8669
8670         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8671         W_ERROR_HAVE_NO_MEMORY(info);
8672
8673         *count = 2;
8674
8675         result = fill_monitor_1(info, &info[0].info1,
8676                                 SPL_LOCAL_PORT);
8677         if (!W_ERROR_IS_OK(result)) {
8678                 goto out;
8679         }
8680
8681         result = fill_monitor_1(info, &info[1].info1,
8682                                 SPL_TCPIP_PORT);
8683         if (!W_ERROR_IS_OK(result)) {
8684                 goto out;
8685         }
8686
8687 out:
8688         if (!W_ERROR_IS_OK(result)) {
8689                 TALLOC_FREE(info);
8690                 *count = 0;
8691                 return result;
8692         }
8693
8694         *info_p = info;
8695
8696         return WERR_OK;
8697 }
8698
8699 /****************************************************************************
8700  enumprintmonitors level 2.
8701 ****************************************************************************/
8702
8703 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8704                                         union spoolss_MonitorInfo **info_p,
8705                                         uint32_t *count)
8706 {
8707         union spoolss_MonitorInfo *info;
8708         WERROR result = WERR_OK;
8709
8710         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8711         W_ERROR_HAVE_NO_MEMORY(info);
8712
8713         *count = 2;
8714
8715         result = fill_monitor_2(info, &info[0].info2,
8716                                 SPL_LOCAL_PORT,
8717                                 "Windows NT X86", /* FIXME */
8718                                 "localmon.dll");
8719         if (!W_ERROR_IS_OK(result)) {
8720                 goto out;
8721         }
8722
8723         result = fill_monitor_2(info, &info[1].info2,
8724                                 SPL_TCPIP_PORT,
8725                                 "Windows NT X86", /* FIXME */
8726                                 "tcpmon.dll");
8727         if (!W_ERROR_IS_OK(result)) {
8728                 goto out;
8729         }
8730
8731 out:
8732         if (!W_ERROR_IS_OK(result)) {
8733                 TALLOC_FREE(info);
8734                 *count = 0;
8735                 return result;
8736         }
8737
8738         *info_p = info;
8739
8740         return WERR_OK;
8741 }
8742
8743 /****************************************************************
8744  _spoolss_EnumMonitors
8745 ****************************************************************/
8746
8747 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
8748                              struct spoolss_EnumMonitors *r)
8749 {
8750         WERROR result;
8751
8752         /* that's an [in out] buffer */
8753
8754         if (!r->in.buffer && (r->in.offered != 0)) {
8755                 return WERR_INVALID_PARAM;
8756         }
8757
8758         DEBUG(5,("_spoolss_EnumMonitors\n"));
8759
8760         /*
8761          * Enumerate the print monitors ...
8762          *
8763          * Just reply with "Local Port", to keep NT happy
8764          * and I can use my nice printer checker.
8765          */
8766
8767         *r->out.count = 0;
8768         *r->out.needed = 0;
8769         *r->out.info = NULL;
8770
8771         switch (r->in.level) {
8772         case 1:
8773                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8774                                                    r->out.count);
8775                 break;
8776         case 2:
8777                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8778                                                    r->out.count);
8779                 break;
8780         default:
8781                 return WERR_UNKNOWN_LEVEL;
8782         }
8783
8784         if (!W_ERROR_IS_OK(result)) {
8785                 return result;
8786         }
8787
8788         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8789                                                      spoolss_EnumMonitors, 
8790                                                      *r->out.info, r->in.level,
8791                                                      *r->out.count);
8792         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8793         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8794
8795         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8796 }
8797
8798 /****************************************************************************
8799 ****************************************************************************/
8800
8801 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8802                              const print_queue_struct *queue,
8803                              int count, int snum,
8804                              struct spoolss_PrinterInfo2 *pinfo2,
8805                              uint32_t jobid,
8806                              struct spoolss_JobInfo1 *r)
8807 {
8808         int i = 0;
8809         bool found = false;
8810
8811         for (i=0; i<count; i++) {
8812                 if (queue[i].job == (int)jobid) {
8813                         found = true;
8814                         break;
8815                 }
8816         }
8817
8818         if (found == false) {
8819                 /* NT treats not found as bad param... yet another bad choice */
8820                 return WERR_INVALID_PARAM;
8821         }
8822
8823         return fill_job_info1(mem_ctx,
8824                               r,
8825                               &queue[i],
8826                               i,
8827                               snum,
8828                               pinfo2);
8829 }
8830
8831 /****************************************************************************
8832 ****************************************************************************/
8833
8834 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
8835                              const print_queue_struct *queue,
8836                              int count, int snum,
8837                              struct spoolss_PrinterInfo2 *pinfo2,
8838                              uint32_t jobid,
8839                              struct spoolss_JobInfo2 *r)
8840 {
8841         int i = 0;
8842         bool found = false;
8843         struct spoolss_DeviceMode *devmode;
8844         WERROR result;
8845
8846         for (i=0; i<count; i++) {
8847                 if (queue[i].job == (int)jobid) {
8848                         found = true;
8849                         break;
8850                 }
8851         }
8852
8853         if (found == false) {
8854                 /* NT treats not found as bad param... yet another bad
8855                    choice */
8856                 return WERR_INVALID_PARAM;
8857         }
8858
8859         /*
8860          * if the print job does not have a DEVMODE associated with it,
8861          * just use the one for the printer. A NULL devicemode is not
8862          *  a failure condition
8863          */
8864
8865         devmode = print_job_devmode(lp_const_servicename(snum), jobid);
8866         if (!devmode) {
8867                 result = spoolss_create_default_devmode(mem_ctx,
8868                                                 pinfo2->printername,
8869                                                 &devmode);
8870                 if (!W_ERROR_IS_OK(result)) {
8871                         DEBUG(3, ("Can't proceed w/o a devmode!"));
8872                         return result;
8873                 }
8874         }
8875
8876         return fill_job_info2(mem_ctx,
8877                               r,
8878                               &queue[i],
8879                               i,
8880                               snum,
8881                               pinfo2,
8882                               devmode);
8883 }
8884
8885 /****************************************************************
8886  _spoolss_GetJob
8887 ****************************************************************/
8888
8889 WERROR _spoolss_GetJob(struct pipes_struct *p,
8890                        struct spoolss_GetJob *r)
8891 {
8892         WERROR result = WERR_OK;
8893         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
8894         int snum;
8895         int count;
8896         print_queue_struct      *queue = NULL;
8897         print_status_struct prt_status;
8898
8899         /* that's an [in out] buffer */
8900
8901         if (!r->in.buffer && (r->in.offered != 0)) {
8902                 return WERR_INVALID_PARAM;
8903         }
8904
8905         DEBUG(5,("_spoolss_GetJob\n"));
8906
8907         *r->out.needed = 0;
8908
8909         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8910                 return WERR_BADFID;
8911         }
8912
8913         result = winreg_get_printer(p->mem_ctx,
8914                                     get_server_info_system(),
8915                                     p->msg_ctx,
8916                                     NULL,
8917                                     lp_const_servicename(snum),
8918                                     &pinfo2);
8919         if (!W_ERROR_IS_OK(result)) {
8920                 return result;
8921         }
8922
8923         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
8924
8925         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8926                      count, prt_status.status, prt_status.message));
8927
8928         switch (r->in.level) {
8929         case 1:
8930                 result = getjob_level_1(p->mem_ctx,
8931                                         queue, count, snum, pinfo2,
8932                                         r->in.job_id, &r->out.info->info1);
8933                 break;
8934         case 2:
8935                 result = getjob_level_2(p->mem_ctx,
8936                                         queue, count, snum, pinfo2,
8937                                         r->in.job_id, &r->out.info->info2);
8938                 break;
8939         default:
8940                 result = WERR_UNKNOWN_LEVEL;
8941                 break;
8942         }
8943
8944         SAFE_FREE(queue);
8945         TALLOC_FREE(pinfo2);
8946
8947         if (!W_ERROR_IS_OK(result)) {
8948                 TALLOC_FREE(r->out.info);
8949                 return result;
8950         }
8951
8952         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
8953                                                                                    r->in.level);
8954         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8955
8956         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8957 }
8958
8959 /****************************************************************
8960  _spoolss_GetPrinterDataEx
8961 ****************************************************************/
8962
8963 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
8964                                  struct spoolss_GetPrinterDataEx *r)
8965 {
8966
8967         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8968         const char *printer;
8969         int                     snum = 0;
8970         WERROR result = WERR_OK;
8971         DATA_BLOB blob;
8972         enum winreg_Type val_type;
8973         uint8_t *val_data;
8974         uint32_t val_size;
8975
8976
8977         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
8978
8979         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
8980                 r->in.key_name, r->in.value_name));
8981
8982         /* in case of problem, return some default values */
8983
8984         *r->out.needed  = 0;
8985         *r->out.type    = REG_NONE;
8986
8987         if (!Printer) {
8988                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8989                         OUR_HANDLE(r->in.handle)));
8990                 result = WERR_BADFID;
8991                 goto done;
8992         }
8993
8994         /* Is the handle to a printer or to the server? */
8995
8996         if (Printer->printer_type == SPLHND_SERVER) {
8997
8998                 union spoolss_PrinterData data;
8999
9000                 result = getprinterdata_printer_server(p->mem_ctx,
9001                                                        r->in.value_name,
9002                                                        r->out.type,
9003                                                        &data);
9004                 if (!W_ERROR_IS_OK(result)) {
9005                         return result;
9006                 }
9007
9008                 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
9009                                                   *r->out.type, &data);
9010                 if (!W_ERROR_IS_OK(result)) {
9011                         return result;
9012                 }
9013
9014                 *r->out.needed = blob.length;
9015
9016                 if (r->in.offered >= *r->out.needed) {
9017                         memcpy(r->out.data, blob.data, blob.length);
9018                 }
9019
9020                 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9021         }
9022
9023         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9024                 return WERR_BADFID;
9025         }
9026         printer = lp_const_servicename(snum);
9027
9028         /* check to see if the keyname is valid */
9029         if (!strlen(r->in.key_name)) {
9030                 return WERR_INVALID_PARAM;
9031         }
9032
9033         /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9034         if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9035             strequal(r->in.value_name, "ChangeId")) {
9036                 *r->out.type = REG_DWORD;
9037                 *r->out.needed = 4;
9038                 if (r->in.offered >= *r->out.needed) {
9039                         uint32_t changeid = 0;
9040
9041                         result = winreg_printer_get_changeid(p->mem_ctx,
9042                                                              get_server_info_system(),
9043                                                              p->msg_ctx,
9044                                                              printer,
9045                                                              &changeid);
9046                         if (!W_ERROR_IS_OK(result)) {
9047                                 return result;
9048                         }
9049
9050                         SIVAL(r->out.data, 0, changeid);
9051                         result = WERR_OK;
9052                 }
9053                 goto done;
9054         }
9055
9056         result = winreg_get_printer_dataex(p->mem_ctx,
9057                                            get_server_info_system(),
9058                                            p->msg_ctx,
9059                                            printer,
9060                                            r->in.key_name,
9061                                            r->in.value_name,
9062                                            &val_type,
9063                                            &val_data,
9064                                            &val_size);
9065         if (!W_ERROR_IS_OK(result)) {
9066                 return result;
9067         }
9068
9069         *r->out.needed = val_size;
9070         *r->out.type = val_type;
9071
9072         if (r->in.offered >= *r->out.needed) {
9073                 memcpy(r->out.data, val_data, val_size);
9074         }
9075
9076  done:
9077         *r->out.type    = SPOOLSS_BUFFER_OK(*r->out.type, REG_NONE);
9078         r->out.data     = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
9079
9080         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9081 }
9082
9083 /****************************************************************
9084  _spoolss_SetPrinterDataEx
9085 ****************************************************************/
9086
9087 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9088                                  struct spoolss_SetPrinterDataEx *r)
9089 {
9090         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9091         int                     snum = 0;
9092         WERROR                  result = WERR_OK;
9093         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9094         char                    *oid_string;
9095
9096         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9097
9098         /* From MSDN documentation of SetPrinterDataEx: pass request to
9099            SetPrinterData if key is "PrinterDriverData" */
9100
9101         if (!Printer) {
9102                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9103                         OUR_HANDLE(r->in.handle)));
9104                 return WERR_BADFID;
9105         }
9106
9107         if (Printer->printer_type == SPLHND_SERVER) {
9108                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9109                         "Not implemented for server handles yet\n"));
9110                 return WERR_INVALID_PARAM;
9111         }
9112
9113         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9114                 return WERR_BADFID;
9115         }
9116
9117         /*
9118          * Access check : NT returns "access denied" if you make a
9119          * SetPrinterData call without the necessary privildge.
9120          * we were originally returning OK if nothing changed
9121          * which made Win2k issue **a lot** of SetPrinterData
9122          * when connecting to a printer  --jerry
9123          */
9124
9125         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9126                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9127                         "change denied by handle access permissions\n"));
9128                 return WERR_ACCESS_DENIED;
9129         }
9130
9131         result = winreg_get_printer(Printer,
9132                                     get_server_info_system(),
9133                                     p->msg_ctx,
9134                                     Printer->servername,
9135                                     lp_servicename(snum),
9136                                     &pinfo2);
9137         if (!W_ERROR_IS_OK(result)) {
9138                 return result;
9139         }
9140
9141         /* check for OID in valuename */
9142
9143         oid_string = strchr(r->in.value_name, ',');
9144         if (oid_string) {
9145                 *oid_string = '\0';
9146                 oid_string++;
9147         }
9148
9149         /* save the registry data */
9150
9151         result = winreg_set_printer_dataex(p->mem_ctx,
9152                                            get_server_info_system(),
9153                                            p->msg_ctx,
9154                                            pinfo2->sharename,
9155                                            r->in.key_name,
9156                                            r->in.value_name,
9157                                            r->in.type,
9158                                            r->in.data,
9159                                            r->in.offered);
9160
9161         if (W_ERROR_IS_OK(result)) {
9162                 /* save the OID if one was specified */
9163                 if (oid_string) {
9164                         char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9165                                 r->in.key_name, SPOOL_OID_KEY);
9166                         if (!str) {
9167                                 result = WERR_NOMEM;
9168                                 goto done;
9169                         }
9170
9171                         /*
9172                          * I'm not checking the status here on purpose.  Don't know
9173                          * if this is right, but I'm returning the status from the
9174                          * previous set_printer_dataex() call.  I have no idea if
9175                          * this is right.    --jerry
9176                          */
9177                         winreg_set_printer_dataex(p->mem_ctx,
9178                                                   get_server_info_system(),
9179                                                   p->msg_ctx,
9180                                                   pinfo2->sharename,
9181                                                   str,
9182                                                   r->in.value_name,
9183                                                   REG_SZ,
9184                                                   (uint8_t *) oid_string,
9185                                                   strlen(oid_string) + 1);
9186                 }
9187
9188                 result = winreg_printer_update_changeid(p->mem_ctx,
9189                                                         get_server_info_system(),
9190                                                         p->msg_ctx,
9191                                                         lp_const_servicename(snum));
9192
9193         }
9194
9195 done:
9196         talloc_free(pinfo2);
9197         return result;
9198 }
9199
9200 /****************************************************************
9201  _spoolss_DeletePrinterDataEx
9202 ****************************************************************/
9203
9204 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9205                                     struct spoolss_DeletePrinterDataEx *r)
9206 {
9207         const char *printer;
9208         int             snum=0;
9209         WERROR          status = WERR_OK;
9210         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9211
9212         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9213
9214         if (!Printer) {
9215                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9216                         "Invalid handle (%s:%u:%u).\n",
9217                         OUR_HANDLE(r->in.handle)));
9218                 return WERR_BADFID;
9219         }
9220
9221         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9222                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9223                         "printer properties change denied by handle\n"));
9224                 return WERR_ACCESS_DENIED;
9225         }
9226
9227         if (!r->in.value_name || !r->in.key_name) {
9228                 return WERR_NOMEM;
9229         }
9230
9231         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9232                 return WERR_BADFID;
9233         }
9234         printer = lp_const_servicename(snum);
9235
9236         status = winreg_delete_printer_dataex(p->mem_ctx,
9237                                               get_server_info_system(),
9238                                               p->msg_ctx,
9239                                               printer,
9240                                               r->in.key_name,
9241                                               r->in.value_name);
9242         if (W_ERROR_IS_OK(status)) {
9243                 status = winreg_printer_update_changeid(p->mem_ctx,
9244                                                         get_server_info_system(),
9245                                                         p->msg_ctx,
9246                                                         printer);
9247         }
9248
9249         return status;
9250 }
9251
9252 /****************************************************************
9253  _spoolss_EnumPrinterKey
9254 ****************************************************************/
9255
9256 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9257                                struct spoolss_EnumPrinterKey *r)
9258 {
9259         uint32_t        num_keys;
9260         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9261         int             snum = 0;
9262         WERROR          result = WERR_BADFILE;
9263         const char **array = NULL;
9264         DATA_BLOB blob;
9265
9266         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9267
9268         if (!Printer) {
9269                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9270                         OUR_HANDLE(r->in.handle)));
9271                 return WERR_BADFID;
9272         }
9273
9274         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9275                 return WERR_BADFID;
9276         }
9277
9278         result = winreg_enum_printer_key(p->mem_ctx,
9279                                          get_server_info_system(),
9280                                          p->msg_ctx,
9281                                          lp_const_servicename(snum),
9282                                          r->in.key_name,
9283                                          &num_keys,
9284                                          &array);
9285         if (!W_ERROR_IS_OK(result)) {
9286                 goto done;
9287         }
9288
9289         if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9290                 result = WERR_NOMEM;
9291                 goto done;
9292         }
9293
9294         *r->out._ndr_size = r->in.offered / 2;
9295         *r->out.needed = blob.length;
9296
9297         if (r->in.offered < *r->out.needed) {
9298                 result = WERR_MORE_DATA;
9299         } else {
9300                 result = WERR_OK;
9301                 r->out.key_buffer->string_array = array;
9302         }
9303
9304  done:
9305         if (!W_ERROR_IS_OK(result)) {
9306                 TALLOC_FREE(array);
9307                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9308                         *r->out.needed = 0;
9309                 }
9310         }
9311
9312         return result;
9313 }
9314
9315 /****************************************************************
9316  _spoolss_DeletePrinterKey
9317 ****************************************************************/
9318
9319 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9320                                  struct spoolss_DeletePrinterKey *r)
9321 {
9322         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9323         int                     snum=0;
9324         WERROR                  status;
9325         const char *printer;
9326
9327         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9328
9329         if (!Printer) {
9330                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9331                         OUR_HANDLE(r->in.handle)));
9332                 return WERR_BADFID;
9333         }
9334
9335         /* if keyname == NULL, return error */
9336         if ( !r->in.key_name )
9337                 return WERR_INVALID_PARAM;
9338
9339         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9340                 return WERR_BADFID;
9341         }
9342
9343         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9344                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9345                         "printer properties change denied by handle\n"));
9346                 return WERR_ACCESS_DENIED;
9347         }
9348
9349         printer = lp_const_servicename(snum);
9350
9351         /* delete the key and all subkeys */
9352         status = winreg_delete_printer_key(p->mem_ctx,
9353                                            get_server_info_system(),
9354                                            p->msg_ctx,
9355                                            printer,
9356                                            r->in.key_name);
9357         if (W_ERROR_IS_OK(status)) {
9358                 status = winreg_printer_update_changeid(p->mem_ctx,
9359                                                         get_server_info_system(),
9360                                                         p->msg_ctx,
9361                                                         printer);
9362         }
9363
9364         return status;
9365 }
9366
9367 /****************************************************************
9368  _spoolss_EnumPrinterDataEx
9369 ****************************************************************/
9370
9371 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
9372                                   struct spoolss_EnumPrinterDataEx *r)
9373 {
9374         uint32_t        count = 0;
9375         struct spoolss_PrinterEnumValues *info = NULL;
9376         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9377         int             snum;
9378         WERROR          result;
9379
9380         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9381
9382         *r->out.count = 0;
9383         *r->out.needed = 0;
9384         *r->out.info = NULL;
9385
9386         if (!Printer) {
9387                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9388                         OUR_HANDLE(r->in.handle)));
9389                 return WERR_BADFID;
9390         }
9391
9392         /*
9393          * first check for a keyname of NULL or "".  Win2k seems to send
9394          * this a lot and we should send back WERR_INVALID_PARAM
9395          * no need to spend time looking up the printer in this case.
9396          * --jerry
9397          */
9398
9399         if (!strlen(r->in.key_name)) {
9400                 result = WERR_INVALID_PARAM;
9401                 goto done;
9402         }
9403
9404         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9405                 return WERR_BADFID;
9406         }
9407
9408         /* now look for a match on the key name */
9409         result = winreg_enum_printer_dataex(p->mem_ctx,
9410                                             get_server_info_system(),
9411                                             p->msg_ctx,
9412                                             lp_const_servicename(snum),
9413                                             r->in.key_name,
9414                                             &count,
9415                                             &info);
9416         if (!W_ERROR_IS_OK(result)) {
9417                 goto done;
9418         }
9419
9420 #if 0 /* FIXME - gd */
9421         /* housekeeping information in the reply */
9422
9423         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9424          * the hand marshalled container size is a multiple
9425          * of 4 bytes for RPC alignment.
9426          */
9427
9428         if (needed % 4) {
9429                 needed += 4-(needed % 4);
9430         }
9431 #endif
9432         *r->out.count   = count;
9433         *r->out.info    = info;
9434
9435  done:
9436         if (!W_ERROR_IS_OK(result)) {
9437                 return result;
9438         }
9439
9440         *r->out.needed  = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9441                                                spoolss_EnumPrinterDataEx, 
9442                                                *r->out.info,
9443                                                *r->out.count);
9444         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9445         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9446
9447         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9448 }
9449
9450 /****************************************************************************
9451 ****************************************************************************/
9452
9453 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9454                                                  const char *servername,
9455                                                  const char *environment,
9456                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
9457 {
9458         WERROR werr;
9459         char *path = NULL;
9460
9461         werr = compose_spoolss_server_path(mem_ctx,
9462                                            servername,
9463                                            environment,
9464                                            SPOOLSS_PRTPROCS_PATH,
9465                                            &path);
9466         if (!W_ERROR_IS_OK(werr)) {
9467                 return werr;
9468         }
9469
9470         DEBUG(4,("print processor directory: [%s]\n", path));
9471
9472         r->directory_name = path;
9473
9474         return WERR_OK;
9475 }
9476
9477 /****************************************************************
9478  _spoolss_GetPrintProcessorDirectory
9479 ****************************************************************/
9480
9481 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
9482                                            struct spoolss_GetPrintProcessorDirectory *r)
9483 {
9484         WERROR result;
9485
9486         /* that's an [in out] buffer */
9487
9488         if (!r->in.buffer && (r->in.offered != 0)) {
9489                 return WERR_INVALID_PARAM;
9490         }
9491
9492         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9493                 r->in.level));
9494
9495         *r->out.needed = 0;
9496
9497         /* r->in.level is ignored */
9498
9499         /* We always should reply with a local print processor directory so that
9500          * users are not forced to have a [prnproc$] share on the Samba spoolss
9501          * server - Guenther */
9502
9503         result = getprintprocessordirectory_level_1(p->mem_ctx,
9504                                                     NULL, /* r->in.server */
9505                                                     r->in.environment,
9506                                                     &r->out.info->info1);
9507         if (!W_ERROR_IS_OK(result)) {
9508                 TALLOC_FREE(r->out.info);
9509                 return result;
9510         }
9511
9512         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
9513                                                                                    r->out.info, r->in.level);
9514         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9515
9516         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9517 }
9518
9519 /*******************************************************************
9520  ********************************************************************/
9521
9522 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9523                                const char *dllname)
9524 {
9525         enum ndr_err_code ndr_err;
9526         struct spoolss_MonitorUi ui;
9527
9528         ui.dll_name = dllname;
9529
9530         ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
9531                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9532         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9533                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9534         }
9535         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9536 }
9537
9538 /*******************************************************************
9539  Streams the monitor UI DLL name in UNICODE
9540 *******************************************************************/
9541
9542 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9543                                NT_USER_TOKEN *token, DATA_BLOB *in,
9544                                DATA_BLOB *out, uint32_t *needed)
9545 {
9546         const char *dllname = "tcpmonui.dll";
9547
9548         *needed = (strlen(dllname)+1) * 2;
9549
9550         if (out->length < *needed) {
9551                 return WERR_INSUFFICIENT_BUFFER;
9552         }
9553
9554         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9555                 return WERR_NOMEM;
9556         }
9557
9558         return WERR_OK;
9559 }
9560
9561 /*******************************************************************
9562  ********************************************************************/
9563
9564 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9565                              struct spoolss_PortData1 *port1,
9566                              const DATA_BLOB *buf)
9567 {
9568         enum ndr_err_code ndr_err;
9569         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
9570                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9571         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9572                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9573         }
9574         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9575 }
9576
9577 /*******************************************************************
9578  ********************************************************************/
9579
9580 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9581                              struct spoolss_PortData2 *port2,
9582                              const DATA_BLOB *buf)
9583 {
9584         enum ndr_err_code ndr_err;
9585         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
9586                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9587         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9588                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9589         }
9590         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9591 }
9592
9593 /*******************************************************************
9594  Create a new TCP/IP port
9595 *******************************************************************/
9596
9597 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9598                              NT_USER_TOKEN *token, DATA_BLOB *in,
9599                              DATA_BLOB *out, uint32_t *needed)
9600 {
9601         struct spoolss_PortData1 port1;
9602         struct spoolss_PortData2 port2;
9603         char *device_uri = NULL;
9604         uint32_t version;
9605
9606         const char *portname;
9607         const char *hostaddress;
9608         const char *queue;
9609         uint32_t port_number;
9610         uint32_t protocol;
9611
9612         /* peek for spoolss_PortData version */
9613
9614         if (!in || (in->length < (128 + 4))) {
9615                 return WERR_GENERAL_FAILURE;
9616         }
9617
9618         version = IVAL(in->data, 128);
9619
9620         switch (version) {
9621                 case 1:
9622                         ZERO_STRUCT(port1);
9623
9624                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
9625                                 return WERR_NOMEM;
9626                         }
9627
9628                         portname        = port1.portname;
9629                         hostaddress     = port1.hostaddress;
9630                         queue           = port1.queue;
9631                         protocol        = port1.protocol;
9632                         port_number     = port1.port_number;
9633
9634                         break;
9635                 case 2:
9636                         ZERO_STRUCT(port2);
9637
9638                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
9639                                 return WERR_NOMEM;
9640                         }
9641
9642                         portname        = port2.portname;
9643                         hostaddress     = port2.hostaddress;
9644                         queue           = port2.queue;
9645                         protocol        = port2.protocol;
9646                         port_number     = port2.port_number;
9647
9648                         break;
9649                 default:
9650                         DEBUG(1,("xcvtcp_addport: "
9651                                 "unknown version of port_data: %d\n", version));
9652                         return WERR_UNKNOWN_PORT;
9653         }
9654
9655         /* create the device URI and call the add_port_hook() */
9656
9657         switch (protocol) {
9658         case PROTOCOL_RAWTCP_TYPE:
9659                 device_uri = talloc_asprintf(mem_ctx,
9660                                 "socket://%s:%d/", hostaddress,
9661                                 port_number);
9662                 break;
9663
9664         case PROTOCOL_LPR_TYPE:
9665                 device_uri = talloc_asprintf(mem_ctx,
9666                         "lpr://%s/%s", hostaddress, queue );
9667                 break;
9668
9669         default:
9670                 return WERR_UNKNOWN_PORT;
9671         }
9672
9673         if (!device_uri) {
9674                 return WERR_NOMEM;
9675         }
9676
9677         return add_port_hook(mem_ctx, token, portname, device_uri);
9678 }
9679
9680 /*******************************************************************
9681 *******************************************************************/
9682
9683 struct xcv_api_table xcvtcp_cmds[] = {
9684         { "MonitorUI",  xcvtcp_monitorui },
9685         { "AddPort",    xcvtcp_addport},
9686         { NULL,         NULL }
9687 };
9688
9689 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9690                                      NT_USER_TOKEN *token, const char *command,
9691                                      DATA_BLOB *inbuf,
9692                                      DATA_BLOB *outbuf,
9693                                      uint32_t *needed )
9694 {
9695         int i;
9696
9697         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9698
9699         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9700                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9701                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9702         }
9703
9704         return WERR_BADFUNC;
9705 }
9706
9707 /*******************************************************************
9708 *******************************************************************/
9709 #if 0   /* don't support management using the "Local Port" monitor */
9710
9711 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9712                                  NT_USER_TOKEN *token, DATA_BLOB *in,
9713                                  DATA_BLOB *out, uint32_t *needed)
9714 {
9715         const char *dllname = "localui.dll";
9716
9717         *needed = (strlen(dllname)+1) * 2;
9718
9719         if (out->length < *needed) {
9720                 return WERR_INSUFFICIENT_BUFFER;
9721         }
9722
9723         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9724                 return WERR_NOMEM;
9725         }
9726
9727         return WERR_OK;
9728 }
9729
9730 /*******************************************************************
9731 *******************************************************************/
9732
9733 struct xcv_api_table xcvlocal_cmds[] = {
9734         { "MonitorUI",  xcvlocal_monitorui },
9735         { NULL,         NULL }
9736 };
9737 #else
9738 struct xcv_api_table xcvlocal_cmds[] = {
9739         { NULL,         NULL }
9740 };
9741 #endif
9742
9743
9744
9745 /*******************************************************************
9746 *******************************************************************/
9747
9748 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9749                                        NT_USER_TOKEN *token, const char *command,
9750                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9751                                        uint32_t *needed)
9752 {
9753         int i;
9754
9755         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9756
9757         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9758                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9759                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9760         }
9761         return WERR_BADFUNC;
9762 }
9763
9764 /****************************************************************
9765  _spoolss_XcvData
9766 ****************************************************************/
9767
9768 WERROR _spoolss_XcvData(struct pipes_struct *p,
9769                         struct spoolss_XcvData *r)
9770 {
9771         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9772         DATA_BLOB out_data = data_blob_null;
9773         WERROR werror;
9774
9775         if (!Printer) {
9776                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9777                         OUR_HANDLE(r->in.handle)));
9778                 return WERR_BADFID;
9779         }
9780
9781         /* Has to be a handle to the TCP/IP port monitor */
9782
9783         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9784                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9785                 return WERR_BADFID;
9786         }
9787
9788         /* requires administrative access to the server */
9789
9790         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9791                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9792                 return WERR_ACCESS_DENIED;
9793         }
9794
9795         /* Allocate the outgoing buffer */
9796
9797         if (r->in.out_data_size) {
9798                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9799                 if (out_data.data == NULL) {
9800                         return WERR_NOMEM;
9801                 }
9802         }
9803
9804         switch ( Printer->printer_type ) {
9805         case SPLHND_PORTMON_TCP:
9806                 werror = process_xcvtcp_command(p->mem_ctx,
9807                                                 p->server_info->ptok,
9808                                                 r->in.function_name,
9809                                                 &r->in.in_data, &out_data,
9810                                                 r->out.needed);
9811                 break;
9812         case SPLHND_PORTMON_LOCAL:
9813                 werror = process_xcvlocal_command(p->mem_ctx,
9814                                                   p->server_info->ptok,
9815                                                   r->in.function_name,
9816                                                   &r->in.in_data, &out_data,
9817                                                   r->out.needed);
9818                 break;
9819         default:
9820                 werror = WERR_INVALID_PRINT_MONITOR;
9821         }
9822
9823         if (!W_ERROR_IS_OK(werror)) {
9824                 return werror;
9825         }
9826
9827         *r->out.status_code = 0;
9828
9829         if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
9830                 memcpy(r->out.out_data, out_data.data,
9831                         MIN(r->in.out_data_size, out_data.length));
9832         }
9833
9834         return WERR_OK;
9835 }
9836
9837 /****************************************************************
9838  _spoolss_AddPrintProcessor
9839 ****************************************************************/
9840
9841 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
9842                                   struct spoolss_AddPrintProcessor *r)
9843 {
9844         /* for now, just indicate success and ignore the add.  We'll
9845            automatically set the winprint processor for printer
9846            entries later.  Used to debug the LexMark Optra S 1855 PCL
9847            driver --jerry */
9848
9849         return WERR_OK;
9850 }
9851
9852 /****************************************************************
9853  _spoolss_AddPort
9854 ****************************************************************/
9855
9856 WERROR _spoolss_AddPort(struct pipes_struct *p,
9857                         struct spoolss_AddPort *r)
9858 {
9859         /* do what w2k3 does */
9860
9861         return WERR_NOT_SUPPORTED;
9862 }
9863
9864 /****************************************************************
9865  _spoolss_GetPrinterDriver
9866 ****************************************************************/
9867
9868 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
9869                                  struct spoolss_GetPrinterDriver *r)
9870 {
9871         p->rng_fault_state = true;
9872         return WERR_NOT_SUPPORTED;
9873 }
9874
9875 /****************************************************************
9876  _spoolss_ReadPrinter
9877 ****************************************************************/
9878
9879 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
9880                             struct spoolss_ReadPrinter *r)
9881 {
9882         p->rng_fault_state = true;
9883         return WERR_NOT_SUPPORTED;
9884 }
9885
9886 /****************************************************************
9887  _spoolss_WaitForPrinterChange
9888 ****************************************************************/
9889
9890 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
9891                                      struct spoolss_WaitForPrinterChange *r)
9892 {
9893         p->rng_fault_state = true;
9894         return WERR_NOT_SUPPORTED;
9895 }
9896
9897 /****************************************************************
9898  _spoolss_ConfigurePort
9899 ****************************************************************/
9900
9901 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
9902                               struct spoolss_ConfigurePort *r)
9903 {
9904         p->rng_fault_state = true;
9905         return WERR_NOT_SUPPORTED;
9906 }
9907
9908 /****************************************************************
9909  _spoolss_DeletePort
9910 ****************************************************************/
9911
9912 WERROR _spoolss_DeletePort(struct pipes_struct *p,
9913                            struct spoolss_DeletePort *r)
9914 {
9915         p->rng_fault_state = true;
9916         return WERR_NOT_SUPPORTED;
9917 }
9918
9919 /****************************************************************
9920  _spoolss_CreatePrinterIC
9921 ****************************************************************/
9922
9923 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
9924                                 struct spoolss_CreatePrinterIC *r)
9925 {
9926         p->rng_fault_state = true;
9927         return WERR_NOT_SUPPORTED;
9928 }
9929
9930 /****************************************************************
9931  _spoolss_PlayGDIScriptOnPrinterIC
9932 ****************************************************************/
9933
9934 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
9935                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
9936 {
9937         p->rng_fault_state = true;
9938         return WERR_NOT_SUPPORTED;
9939 }
9940
9941 /****************************************************************
9942  _spoolss_DeletePrinterIC
9943 ****************************************************************/
9944
9945 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
9946                                 struct spoolss_DeletePrinterIC *r)
9947 {
9948         p->rng_fault_state = true;
9949         return WERR_NOT_SUPPORTED;
9950 }
9951
9952 /****************************************************************
9953  _spoolss_AddPrinterConnection
9954 ****************************************************************/
9955
9956 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
9957                                      struct spoolss_AddPrinterConnection *r)
9958 {
9959         p->rng_fault_state = true;
9960         return WERR_NOT_SUPPORTED;
9961 }
9962
9963 /****************************************************************
9964  _spoolss_DeletePrinterConnection
9965 ****************************************************************/
9966
9967 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
9968                                         struct spoolss_DeletePrinterConnection *r)
9969 {
9970         p->rng_fault_state = true;
9971         return WERR_NOT_SUPPORTED;
9972 }
9973
9974 /****************************************************************
9975  _spoolss_PrinterMessageBox
9976 ****************************************************************/
9977
9978 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
9979                                   struct spoolss_PrinterMessageBox *r)
9980 {
9981         p->rng_fault_state = true;
9982         return WERR_NOT_SUPPORTED;
9983 }
9984
9985 /****************************************************************
9986  _spoolss_AddMonitor
9987 ****************************************************************/
9988
9989 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
9990                            struct spoolss_AddMonitor *r)
9991 {
9992         p->rng_fault_state = true;
9993         return WERR_NOT_SUPPORTED;
9994 }
9995
9996 /****************************************************************
9997  _spoolss_DeleteMonitor
9998 ****************************************************************/
9999
10000 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10001                               struct spoolss_DeleteMonitor *r)
10002 {
10003         p->rng_fault_state = true;
10004         return WERR_NOT_SUPPORTED;
10005 }
10006
10007 /****************************************************************
10008  _spoolss_DeletePrintProcessor
10009 ****************************************************************/
10010
10011 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10012                                      struct spoolss_DeletePrintProcessor *r)
10013 {
10014         p->rng_fault_state = true;
10015         return WERR_NOT_SUPPORTED;
10016 }
10017
10018 /****************************************************************
10019  _spoolss_AddPrintProvidor
10020 ****************************************************************/
10021
10022 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10023                                  struct spoolss_AddPrintProvidor *r)
10024 {
10025         p->rng_fault_state = true;
10026         return WERR_NOT_SUPPORTED;
10027 }
10028
10029 /****************************************************************
10030  _spoolss_DeletePrintProvidor
10031 ****************************************************************/
10032
10033 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10034                                     struct spoolss_DeletePrintProvidor *r)
10035 {
10036         p->rng_fault_state = true;
10037         return WERR_NOT_SUPPORTED;
10038 }
10039
10040 /****************************************************************
10041  _spoolss_FindFirstPrinterChangeNotification
10042 ****************************************************************/
10043
10044 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10045                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
10046 {
10047         p->rng_fault_state = true;
10048         return WERR_NOT_SUPPORTED;
10049 }
10050
10051 /****************************************************************
10052  _spoolss_FindNextPrinterChangeNotification
10053 ****************************************************************/
10054
10055 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10056                                                   struct spoolss_FindNextPrinterChangeNotification *r)
10057 {
10058         p->rng_fault_state = true;
10059         return WERR_NOT_SUPPORTED;
10060 }
10061
10062 /****************************************************************
10063  _spoolss_RouterFindFirstPrinterChangeNotificationOld
10064 ****************************************************************/
10065
10066 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10067                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10068 {
10069         p->rng_fault_state = true;
10070         return WERR_NOT_SUPPORTED;
10071 }
10072
10073 /****************************************************************
10074  _spoolss_ReplyOpenPrinter
10075 ****************************************************************/
10076
10077 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10078                                  struct spoolss_ReplyOpenPrinter *r)
10079 {
10080         p->rng_fault_state = true;
10081         return WERR_NOT_SUPPORTED;
10082 }
10083
10084 /****************************************************************
10085  _spoolss_RouterReplyPrinter
10086 ****************************************************************/
10087
10088 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10089                                    struct spoolss_RouterReplyPrinter *r)
10090 {
10091         p->rng_fault_state = true;
10092         return WERR_NOT_SUPPORTED;
10093 }
10094
10095 /****************************************************************
10096  _spoolss_ReplyClosePrinter
10097 ****************************************************************/
10098
10099 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10100                                   struct spoolss_ReplyClosePrinter *r)
10101 {
10102         p->rng_fault_state = true;
10103         return WERR_NOT_SUPPORTED;
10104 }
10105
10106 /****************************************************************
10107  _spoolss_AddPortEx
10108 ****************************************************************/
10109
10110 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10111                           struct spoolss_AddPortEx *r)
10112 {
10113         p->rng_fault_state = true;
10114         return WERR_NOT_SUPPORTED;
10115 }
10116
10117 /****************************************************************
10118  _spoolss_RouterFindFirstPrinterChangeNotification
10119 ****************************************************************/
10120
10121 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10122                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10123 {
10124         p->rng_fault_state = true;
10125         return WERR_NOT_SUPPORTED;
10126 }
10127
10128 /****************************************************************
10129  _spoolss_SpoolerInit
10130 ****************************************************************/
10131
10132 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10133                             struct spoolss_SpoolerInit *r)
10134 {
10135         p->rng_fault_state = true;
10136         return WERR_NOT_SUPPORTED;
10137 }
10138
10139 /****************************************************************
10140  _spoolss_ResetPrinterEx
10141 ****************************************************************/
10142
10143 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10144                                struct spoolss_ResetPrinterEx *r)
10145 {
10146         p->rng_fault_state = true;
10147         return WERR_NOT_SUPPORTED;
10148 }
10149
10150 /****************************************************************
10151  _spoolss_RouterReplyPrinterEx
10152 ****************************************************************/
10153
10154 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10155                                      struct spoolss_RouterReplyPrinterEx *r)
10156 {
10157         p->rng_fault_state = true;
10158         return WERR_NOT_SUPPORTED;
10159 }
10160
10161 /****************************************************************
10162  _spoolss_44
10163 ****************************************************************/
10164
10165 WERROR _spoolss_44(struct pipes_struct *p,
10166                    struct spoolss_44 *r)
10167 {
10168         p->rng_fault_state = true;
10169         return WERR_NOT_SUPPORTED;
10170 }
10171
10172 /****************************************************************
10173  _spoolss_47
10174 ****************************************************************/
10175
10176 WERROR _spoolss_47(struct pipes_struct *p,
10177                    struct spoolss_47 *r)
10178 {
10179         p->rng_fault_state = true;
10180         return WERR_NOT_SUPPORTED;
10181 }
10182
10183 /****************************************************************
10184  _spoolss_4a
10185 ****************************************************************/
10186
10187 WERROR _spoolss_4a(struct pipes_struct *p,
10188                    struct spoolss_4a *r)
10189 {
10190         p->rng_fault_state = true;
10191         return WERR_NOT_SUPPORTED;
10192 }
10193
10194 /****************************************************************
10195  _spoolss_4b
10196 ****************************************************************/
10197
10198 WERROR _spoolss_4b(struct pipes_struct *p,
10199                    struct spoolss_4b *r)
10200 {
10201         p->rng_fault_state = true;
10202         return WERR_NOT_SUPPORTED;
10203 }
10204
10205 /****************************************************************
10206  _spoolss_4c
10207 ****************************************************************/
10208
10209 WERROR _spoolss_4c(struct pipes_struct *p,
10210                    struct spoolss_4c *r)
10211 {
10212         p->rng_fault_state = true;
10213         return WERR_NOT_SUPPORTED;
10214 }
10215
10216 /****************************************************************
10217  _spoolss_53
10218 ****************************************************************/
10219
10220 WERROR _spoolss_53(struct pipes_struct *p,
10221                    struct spoolss_53 *r)
10222 {
10223         p->rng_fault_state = true;
10224         return WERR_NOT_SUPPORTED;
10225 }
10226
10227 /****************************************************************
10228  _spoolss_55
10229 ****************************************************************/
10230
10231 WERROR _spoolss_55(struct pipes_struct *p,
10232                    struct spoolss_55 *r)
10233 {
10234         p->rng_fault_state = true;
10235         return WERR_NOT_SUPPORTED;
10236 }
10237
10238 /****************************************************************
10239  _spoolss_56
10240 ****************************************************************/
10241
10242 WERROR _spoolss_56(struct pipes_struct *p,
10243                    struct spoolss_56 *r)
10244 {
10245         p->rng_fault_state = true;
10246         return WERR_NOT_SUPPORTED;
10247 }
10248
10249 /****************************************************************
10250  _spoolss_57
10251 ****************************************************************/
10252
10253 WERROR _spoolss_57(struct pipes_struct *p,
10254                    struct spoolss_57 *r)
10255 {
10256         p->rng_fault_state = true;
10257         return WERR_NOT_SUPPORTED;
10258 }
10259
10260 /****************************************************************
10261  _spoolss_5a
10262 ****************************************************************/
10263
10264 WERROR _spoolss_5a(struct pipes_struct *p,
10265                    struct spoolss_5a *r)
10266 {
10267         p->rng_fault_state = true;
10268         return WERR_NOT_SUPPORTED;
10269 }
10270
10271 /****************************************************************
10272  _spoolss_5b
10273 ****************************************************************/
10274
10275 WERROR _spoolss_5b(struct pipes_struct *p,
10276                    struct spoolss_5b *r)
10277 {
10278         p->rng_fault_state = true;
10279         return WERR_NOT_SUPPORTED;
10280 }
10281
10282 /****************************************************************
10283  _spoolss_5c
10284 ****************************************************************/
10285
10286 WERROR _spoolss_5c(struct pipes_struct *p,
10287                    struct spoolss_5c *r)
10288 {
10289         p->rng_fault_state = true;
10290         return WERR_NOT_SUPPORTED;
10291 }
10292
10293 /****************************************************************
10294  _spoolss_5d
10295 ****************************************************************/
10296
10297 WERROR _spoolss_5d(struct pipes_struct *p,
10298                    struct spoolss_5d *r)
10299 {
10300         p->rng_fault_state = true;
10301         return WERR_NOT_SUPPORTED;
10302 }
10303
10304 /****************************************************************
10305  _spoolss_5e
10306 ****************************************************************/
10307
10308 WERROR _spoolss_5e(struct pipes_struct *p,
10309                    struct spoolss_5e *r)
10310 {
10311         p->rng_fault_state = true;
10312         return WERR_NOT_SUPPORTED;
10313 }
10314
10315 /****************************************************************
10316  _spoolss_5f
10317 ****************************************************************/
10318
10319 WERROR _spoolss_5f(struct pipes_struct *p,
10320                    struct spoolss_5f *r)
10321 {
10322         p->rng_fault_state = true;
10323         return WERR_NOT_SUPPORTED;
10324 }
10325
10326 /****************************************************************
10327  _spoolss_60
10328 ****************************************************************/
10329
10330 WERROR _spoolss_60(struct pipes_struct *p,
10331                    struct spoolss_60 *r)
10332 {
10333         p->rng_fault_state = true;
10334         return WERR_NOT_SUPPORTED;
10335 }
10336
10337 /****************************************************************
10338  _spoolss_61
10339 ****************************************************************/
10340
10341 WERROR _spoolss_61(struct pipes_struct *p,
10342                    struct spoolss_61 *r)
10343 {
10344         p->rng_fault_state = true;
10345         return WERR_NOT_SUPPORTED;
10346 }
10347
10348 /****************************************************************
10349  _spoolss_62
10350 ****************************************************************/
10351
10352 WERROR _spoolss_62(struct pipes_struct *p,
10353                    struct spoolss_62 *r)
10354 {
10355         p->rng_fault_state = true;
10356         return WERR_NOT_SUPPORTED;
10357 }
10358
10359 /****************************************************************
10360  _spoolss_63
10361 ****************************************************************/
10362
10363 WERROR _spoolss_63(struct pipes_struct *p,
10364                    struct spoolss_63 *r)
10365 {
10366         p->rng_fault_state = true;
10367         return WERR_NOT_SUPPORTED;
10368 }
10369
10370 /****************************************************************
10371  _spoolss_64
10372 ****************************************************************/
10373
10374 WERROR _spoolss_64(struct pipes_struct *p,
10375                    struct spoolss_64 *r)
10376 {
10377         p->rng_fault_state = true;
10378         return WERR_NOT_SUPPORTED;
10379 }
10380
10381 /****************************************************************
10382  _spoolss_65
10383 ****************************************************************/
10384
10385 WERROR _spoolss_65(struct pipes_struct *p,
10386                    struct spoolss_65 *r)
10387 {
10388         p->rng_fault_state = true;
10389         return WERR_NOT_SUPPORTED;
10390 }
10391
10392 /****************************************************************
10393  _spoolss_GetCorePrinterDrivers
10394 ****************************************************************/
10395
10396 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
10397                                       struct spoolss_GetCorePrinterDrivers *r)
10398 {
10399         p->rng_fault_state = true;
10400         return WERR_NOT_SUPPORTED;
10401 }
10402
10403 /****************************************************************
10404  _spoolss_67
10405 ****************************************************************/
10406
10407 WERROR _spoolss_67(struct pipes_struct *p,
10408                    struct spoolss_67 *r)
10409 {
10410         p->rng_fault_state = true;
10411         return WERR_NOT_SUPPORTED;
10412 }
10413
10414 /****************************************************************
10415  _spoolss_GetPrinterDriverPackagePath
10416 ****************************************************************/
10417
10418 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
10419                                             struct spoolss_GetPrinterDriverPackagePath *r)
10420 {
10421         p->rng_fault_state = true;
10422         return WERR_NOT_SUPPORTED;
10423 }
10424
10425 /****************************************************************
10426  _spoolss_69
10427 ****************************************************************/
10428
10429 WERROR _spoolss_69(struct pipes_struct *p,
10430                    struct spoolss_69 *r)
10431 {
10432         p->rng_fault_state = true;
10433         return WERR_NOT_SUPPORTED;
10434 }
10435
10436 /****************************************************************
10437  _spoolss_6a
10438 ****************************************************************/
10439
10440 WERROR _spoolss_6a(struct pipes_struct *p,
10441                    struct spoolss_6a *r)
10442 {
10443         p->rng_fault_state = true;
10444         return WERR_NOT_SUPPORTED;
10445 }
10446
10447 /****************************************************************
10448  _spoolss_6b
10449 ****************************************************************/
10450
10451 WERROR _spoolss_6b(struct pipes_struct *p,
10452                    struct spoolss_6b *r)
10453 {
10454         p->rng_fault_state = true;
10455         return WERR_NOT_SUPPORTED;
10456 }
10457
10458 /****************************************************************
10459  _spoolss_6c
10460 ****************************************************************/
10461
10462 WERROR _spoolss_6c(struct pipes_struct *p,
10463                    struct spoolss_6c *r)
10464 {
10465         p->rng_fault_state = true;
10466         return WERR_NOT_SUPPORTED;
10467 }
10468
10469 /****************************************************************
10470  _spoolss_6d
10471 ****************************************************************/
10472
10473 WERROR _spoolss_6d(struct pipes_struct *p,
10474                    struct spoolss_6d *r)
10475 {
10476         p->rng_fault_state = true;
10477         return WERR_NOT_SUPPORTED;
10478 }