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