s3-spoolss: make it possible to have and announce a [prnproc$] share on the printserver.
[mat/samba.git] / source3 / rpc_server / srv_spoolss_nt.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-2000,
5  *  Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6  *  Copyright (C) Jean François Micouleau      1998-2000,
7  *  Copyright (C) Jeremy Allison               2001-2002,
8  *  Copyright (C) Gerald Carter                2000-2004,
9  *  Copyright (C) Tim Potter                   2001-2002.
10  *  Copyright (C) Guenther Deschner            2009-2010.
11  *  Copyright (C) Andreas Schneider            2010.
12  *
13  *  This program is free software; you can redistribute it and/or modify
14  *  it under the terms of the GNU General Public License as published by
15  *  the Free Software Foundation; either version 3 of the License, or
16  *  (at your option) any later version.
17  *
18  *  This program is distributed in the hope that it will be useful,
19  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
20  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  *  GNU General Public License for more details.
22  *
23  *  You should have received a copy of the GNU General Public License
24  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
25  */
26
27 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
28    up, all the errors returned are DOS errors, not NT status codes. */
29
30 #include "includes.h"
31 #include "nt_printing.h"
32 #include "srv_spoolss_util.h"
33 #include "../librpc/gen_ndr/srv_spoolss.h"
34 #include "../librpc/gen_ndr/cli_spoolss.h"
35 #include "rpc_client/init_spoolss.h"
36 #include "librpc/gen_ndr/messaging.h"
37 #include "librpc/gen_ndr/ndr_security.h"
38 #include "registry.h"
39 #include "registry/reg_objects.h"
40 #include "include/printing.h"
41 #include "secrets.h"
42 #include "../librpc/gen_ndr/netlogon.h"
43 #include "rpc_misc.h"
44
45 /* macros stolen from s4 spoolss server */
46 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
47         ((info)?ndr_size_##fn(info, level, 0):0)
48
49 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
50         ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
51
52 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
53         ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
54
55 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
56
57 #undef DBGC_CLASS
58 #define DBGC_CLASS DBGC_RPC_SRV
59
60 #ifndef MAX_OPEN_PRINTER_EXS
61 #define MAX_OPEN_PRINTER_EXS 50
62 #endif
63
64 struct notify_back_channel;
65
66 /* structure to store the printer handles */
67 /* and a reference to what it's pointing to */
68 /* and the notify info asked about */
69 /* that's the central struct */
70 struct printer_handle {
71         struct printer_handle *prev, *next;
72         bool document_started;
73         bool page_started;
74         uint32 jobid; /* jobid in printing backend */
75         int printer_type;
76         const char *servername;
77         fstring sharename;
78         uint32 type;
79         uint32 access_granted;
80         struct {
81                 uint32 flags;
82                 uint32 options;
83                 fstring localmachine;
84                 uint32 printerlocal;
85                 struct spoolss_NotifyOption *option;
86                 struct policy_handle cli_hnd;
87                 struct notify_back_channel *cli_chan;
88                 uint32 change;
89                 /* are we in a FindNextPrinterChangeNotify() call? */
90                 bool fnpcn;
91                 struct messaging_context *msg_ctx;
92         } notify;
93         struct {
94                 fstring machine;
95                 fstring user;
96         } client;
97
98         /* devmode sent in the OpenPrinter() call */
99         struct spoolss_DeviceMode *devmode;
100
101         /* TODO cache the printer info2 structure */
102         struct spoolss_PrinterInfo2 *info2;
103
104 };
105
106 static struct printer_handle *printers_list;
107
108 struct printer_session_counter {
109         struct printer_session_counter *next;
110         struct printer_session_counter *prev;
111
112         int snum;
113         uint32_t counter;
114 };
115
116 static struct printer_session_counter *counter_list;
117
118 struct notify_back_channel {
119         struct notify_back_channel *prev, *next;
120
121         /* associated client */
122         struct sockaddr_storage client_address;
123
124         /* print notify back-channel pipe handle*/
125         struct rpc_pipe_client *cli_pipe;
126         uint32_t active_connections;
127 };
128
129 static struct notify_back_channel *back_channels;
130
131 /* Map generic permissions to printer object specific permissions */
132
133 const struct standard_mapping printer_std_mapping = {
134         PRINTER_READ,
135         PRINTER_WRITE,
136         PRINTER_EXECUTE,
137         PRINTER_ALL_ACCESS
138 };
139
140 /* Map generic permissions to print server object specific permissions */
141
142 const struct standard_mapping printserver_std_mapping = {
143         SERVER_READ,
144         SERVER_WRITE,
145         SERVER_EXECUTE,
146         SERVER_ALL_ACCESS
147 };
148
149 /* API table for Xcv Monitor functions */
150
151 struct xcv_api_table {
152         const char *name;
153         WERROR(*fn) (TALLOC_CTX *mem_ctx, struct security_token *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
154 };
155
156 static void prune_printername_cache(void);
157
158 /********************************************************************
159  * Canonicalize servername.
160  ********************************************************************/
161
162 static const char *canon_servername(const char *servername)
163 {
164         const char *pservername = servername;
165         while (*pservername == '\\') {
166                 pservername++;
167         }
168         return pservername;
169 }
170
171 /* translate between internal status numbers and NT status numbers */
172 static int nt_printj_status(int v)
173 {
174         switch (v) {
175         case LPQ_QUEUED:
176                 return 0;
177         case LPQ_PAUSED:
178                 return JOB_STATUS_PAUSED;
179         case LPQ_SPOOLING:
180                 return JOB_STATUS_SPOOLING;
181         case LPQ_PRINTING:
182                 return JOB_STATUS_PRINTING;
183         case LPQ_ERROR:
184                 return JOB_STATUS_ERROR;
185         case LPQ_DELETING:
186                 return JOB_STATUS_DELETING;
187         case LPQ_OFFLINE:
188                 return JOB_STATUS_OFFLINE;
189         case LPQ_PAPEROUT:
190                 return JOB_STATUS_PAPEROUT;
191         case LPQ_PRINTED:
192                 return JOB_STATUS_PRINTED;
193         case LPQ_DELETED:
194                 return JOB_STATUS_DELETED;
195         case LPQ_BLOCKED:
196                 return JOB_STATUS_BLOCKED_DEVQ;
197         case LPQ_USER_INTERVENTION:
198                 return JOB_STATUS_USER_INTERVENTION;
199         }
200         return 0;
201 }
202
203 static int nt_printq_status(int v)
204 {
205         switch (v) {
206         case LPQ_PAUSED:
207                 return PRINTER_STATUS_PAUSED;
208         case LPQ_QUEUED:
209         case LPQ_SPOOLING:
210         case LPQ_PRINTING:
211                 return 0;
212         }
213         return 0;
214 }
215
216 /***************************************************************************
217  Disconnect from the client
218 ****************************************************************************/
219
220 static void srv_spoolss_replycloseprinter(int snum,
221                                           struct printer_handle *prn_hnd)
222 {
223         WERROR result;
224         NTSTATUS status;
225
226         /*
227          * Tell the specific printing tdb we no longer want messages for this printer
228          * by deregistering our PID.
229          */
230
231         if (!print_notify_deregister_pid(snum)) {
232                 DEBUG(0, ("Failed to register our pid for printer %s\n",
233                           lp_const_servicename(snum)));
234         }
235
236         /* weird if the test succeeds !!! */
237         if (prn_hnd->notify.cli_chan == NULL ||
238             prn_hnd->notify.cli_chan->active_connections == 0) {
239                 DEBUG(0, ("Trying to close unexisting backchannel!\n"));
240                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
241                 TALLOC_FREE(prn_hnd->notify.cli_chan);
242                 return;
243         }
244
245         status = rpccli_spoolss_ReplyClosePrinter(
246                                         prn_hnd->notify.cli_chan->cli_pipe,
247                                         talloc_tos(),
248                                         &prn_hnd->notify.cli_hnd,
249                                         &result);
250         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
251                 DEBUG(0, ("reply_close_printer failed [%s].\n",
252                           win_errstr(result)));
253         }
254
255         /* if it's the last connection, deconnect the IPC$ share */
256         if (prn_hnd->notify.cli_chan->active_connections == 1) {
257
258                 cli_shutdown(rpc_pipe_np_smb_conn(prn_hnd->notify.cli_chan->cli_pipe));
259                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
260                 TALLOC_FREE(prn_hnd->notify.cli_chan);
261
262                 if (prn_hnd->notify.msg_ctx != NULL) {
263                         messaging_deregister(prn_hnd->notify.msg_ctx,
264                                              MSG_PRINTER_NOTIFY2, NULL);
265
266                         /*
267                          * Tell the serverid.tdb we're no longer
268                          * interested in printer notify messages.
269                          */
270
271                         serverid_register_msg_flags(
272                                 messaging_server_id(prn_hnd->notify.msg_ctx),
273                                 false, FLAG_MSG_PRINT_NOTIFY);
274                 }
275         }
276
277         if (prn_hnd->notify.cli_chan) {
278                 prn_hnd->notify.cli_chan->active_connections--;
279         }
280 }
281
282 /****************************************************************************
283  Functions to free a printer entry datastruct.
284 ****************************************************************************/
285
286 static int printer_entry_destructor(struct printer_handle *Printer)
287 {
288         if (Printer->notify.cli_chan != NULL &&
289             Printer->notify.cli_chan->active_connections > 0) {
290                 int snum = -1;
291
292                 switch(Printer->printer_type) {
293                 case SPLHND_SERVER:
294                         srv_spoolss_replycloseprinter(snum, Printer);
295                         break;
296
297                 case SPLHND_PRINTER:
298                         snum = print_queue_snum(Printer->sharename);
299                         if (snum != -1) {
300                                 srv_spoolss_replycloseprinter(snum, Printer);
301                         }
302                         break;
303                 default:
304                         break;
305                 }
306         }
307
308         Printer->notify.flags=0;
309         Printer->notify.options=0;
310         Printer->notify.localmachine[0]='\0';
311         Printer->notify.printerlocal=0;
312         TALLOC_FREE(Printer->notify.option);
313         TALLOC_FREE(Printer->devmode);
314
315         /* Remove from the internal list. */
316         DLIST_REMOVE(printers_list, Printer);
317         return 0;
318 }
319
320 /****************************************************************************
321   find printer index by handle
322 ****************************************************************************/
323
324 static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
325                                                         struct policy_handle *hnd)
326 {
327         struct printer_handle *find_printer = NULL;
328
329         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
330                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
331                 return NULL;
332         }
333
334         return find_printer;
335 }
336
337 /****************************************************************************
338  Close printer index by handle.
339 ****************************************************************************/
340
341 static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
342 {
343         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
344
345         if (!Printer) {
346                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
347                         OUR_HANDLE(hnd)));
348                 return false;
349         }
350
351         close_policy_hnd(p, hnd);
352
353         return true;
354 }
355
356 /****************************************************************************
357  Delete a printer given a handle.
358 ****************************************************************************/
359
360 static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
361                                   const char *sharename,
362                                   struct messaging_context *msg_ctx)
363 {
364         char *cmd = lp_deleteprinter_cmd();
365         char *command = NULL;
366         int ret;
367         bool is_print_op = false;
368
369         /* can't fail if we don't try */
370
371         if ( !*cmd )
372                 return WERR_OK;
373
374         command = talloc_asprintf(ctx,
375                         "%s \"%s\"",
376                         cmd, sharename);
377         if (!command) {
378                 return WERR_NOMEM;
379         }
380         if ( token )
381                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
382
383         DEBUG(10,("Running [%s]\n", command));
384
385         /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
386
387         if ( is_print_op )
388                 become_root();
389
390         if ( (ret = smbrun(command, NULL)) == 0 ) {
391                 /* Tell everyone we updated smb.conf. */
392                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
393         }
394
395         if ( is_print_op )
396                 unbecome_root();
397
398         /********** END SePrintOperatorPrivlege BLOCK **********/
399
400         DEBUGADD(10,("returned [%d]\n", ret));
401
402         TALLOC_FREE(command);
403
404         if (ret != 0)
405                 return WERR_BADFID; /* What to return here? */
406
407         /* go ahead and re-read the services immediately */
408         become_root();
409         reload_services(msg_ctx, -1, false);
410         unbecome_root();
411
412         if ( lp_servicenumber( sharename ) >= 0 )
413                 return WERR_ACCESS_DENIED;
414
415         return WERR_OK;
416 }
417
418 /****************************************************************************
419  Delete a printer given a handle.
420 ****************************************************************************/
421
422 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
423 {
424         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
425         WERROR result;
426
427         if (!Printer) {
428                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
429                         OUR_HANDLE(hnd)));
430                 return WERR_BADFID;
431         }
432
433         /*
434          * It turns out that Windows allows delete printer on a handle
435          * opened by an admin user, then used on a pipe handle created
436          * by an anonymous user..... but they're working on security.... riiight !
437          * JRA.
438          */
439
440         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
441                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
442                 return WERR_ACCESS_DENIED;
443         }
444
445         /* this does not need a become root since the access check has been
446            done on the handle already */
447
448         result = winreg_delete_printer_key(p->mem_ctx,
449                                            get_server_info_system(),
450                                            p->msg_ctx,
451                                            Printer->sharename,
452                                            "");
453         if (!W_ERROR_IS_OK(result)) {
454                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
455                 return WERR_BADFID;
456         }
457
458         result = delete_printer_hook(p->mem_ctx, p->server_info->ptok,
459                                      Printer->sharename, p->msg_ctx);
460         if (!W_ERROR_IS_OK(result)) {
461                 return result;
462         }
463         prune_printername_cache();
464         return WERR_OK;
465 }
466
467 /****************************************************************************
468  Return the snum of a printer corresponding to an handle.
469 ****************************************************************************/
470
471 static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
472                              int *number, struct share_params **params)
473 {
474         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
475
476         if (!Printer) {
477                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
478                         OUR_HANDLE(hnd)));
479                 return false;
480         }
481
482         switch (Printer->printer_type) {
483                 case SPLHND_PRINTER:
484                         DEBUG(4,("short name:%s\n", Printer->sharename));
485                         *number = print_queue_snum(Printer->sharename);
486                         return (*number != -1);
487                 case SPLHND_SERVER:
488                         return false;
489                 default:
490                         return false;
491         }
492 }
493
494 /****************************************************************************
495  Set printer handle type.
496  Check if it's \\server or \\server\printer
497 ****************************************************************************/
498
499 static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
500 {
501         DEBUG(3,("Setting printer type=%s\n", handlename));
502
503         /* it's a print server */
504         if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
505                 DEBUGADD(4,("Printer is a print server\n"));
506                 Printer->printer_type = SPLHND_SERVER;
507         }
508         /* it's a printer (set_printer_hnd_name() will handle port monitors */
509         else {
510                 DEBUGADD(4,("Printer is a printer\n"));
511                 Printer->printer_type = SPLHND_PRINTER;
512         }
513
514         return true;
515 }
516
517 static void prune_printername_cache_fn(const char *key, const char *value,
518                                        time_t timeout, void *private_data)
519 {
520         gencache_del(key);
521 }
522
523 static void prune_printername_cache(void)
524 {
525         gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
526 }
527
528 /****************************************************************************
529  Set printer handle name..  Accept names like \\server, \\server\printer,
530  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
531  the MSDN docs regarding OpenPrinter() for details on the XcvData() and
532  XcvDataPort() interface.
533 ****************************************************************************/
534
535 static bool set_printer_hnd_name(TALLOC_CTX *mem_ctx,
536                                  const struct auth_serversupplied_info *server_info,
537                                  struct messaging_context *msg_ctx,
538                                  struct printer_handle *Printer,
539                                  const char *handlename)
540 {
541         int snum;
542         int n_services=lp_numservices();
543         char *aprinter;
544         const char *printername;
545         const char *servername = NULL;
546         fstring sname;
547         bool found = false;
548         struct spoolss_PrinterInfo2 *info2 = NULL;
549         WERROR result;
550         char *p;
551
552         /*
553          * Hopefully nobody names his printers like this. Maybe \ or ,
554          * are illegal in printer names even?
555          */
556         const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
557         char *cache_key;
558         char *tmp;
559
560         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
561                 (unsigned long)strlen(handlename)));
562
563         aprinter = CONST_DISCARD(char *, handlename);
564         if ( *handlename == '\\' ) {
565                 servername = canon_servername(handlename);
566                 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
567                         *aprinter = '\0';
568                         aprinter++;
569                 }
570                 if (!is_myname_or_ipaddr(servername)) {
571                         return false;
572                 }
573                 Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
574                 if (Printer->servername == NULL) {
575                         return false;
576                 }
577         }
578
579         if (Printer->printer_type == SPLHND_SERVER) {
580                 return true;
581         }
582
583         if (Printer->printer_type != SPLHND_PRINTER) {
584                 return false;
585         }
586
587         DEBUGADD(5, ("searching for [%s]\n", aprinter));
588
589         if ((p = strchr(aprinter, ',')) != NULL) {
590                 if (*p == ' ')
591                         p++;
592                 if (strnequal(p+1, "DrvConvert", strlen("DrvConvert")) ||
593                     strnequal(p+1, " DrvConvert", strlen(" DrvConvert"))) {
594                         *p = '\0';
595                 } else if (strnequal(p+1, "LocalOnly", strlen("LocalOnly")) ||
596                            strnequal(p+1, " LocalOnly", strlen(" LocalOnly"))) {
597                         *p = '\0';
598                 }
599         }
600
601         /* check for the Port Monitor Interface */
602         if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
603                 Printer->printer_type = SPLHND_PORTMON_TCP;
604                 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
605                 found = true;
606         }
607         else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
608                 Printer->printer_type = SPLHND_PORTMON_LOCAL;
609                 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
610                 found = true;
611         }
612
613         /*
614          * With hundreds of printers, the "for" loop iterating all
615          * shares can be quite expensive, as it is done on every
616          * OpenPrinter. The loop maps "aprinter" to "sname", the
617          * result of which we cache in gencache.
618          */
619
620         cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s",
621                                     aprinter);
622         if ((cache_key != NULL) && gencache_get(cache_key, &tmp, NULL)) {
623
624                 found = (strcmp(tmp, printer_not_found) != 0);
625                 if (!found) {
626                         DEBUG(4, ("Printer %s not found\n", aprinter));
627                         SAFE_FREE(tmp);
628                         return false;
629                 }
630                 fstrcpy(sname, tmp);
631                 SAFE_FREE(tmp);
632         }
633
634         /* Search all sharenames first as this is easier than pulling
635            the printer_info_2 off of disk. Don't use find_service() since
636            that calls out to map_username() */
637
638         /* do another loop to look for printernames */
639         for (snum = 0; !found && snum < n_services; snum++) {
640                 const char *printer = lp_const_servicename(snum);
641
642                 /* no point going on if this is not a printer */
643                 if (!(lp_snum_ok(snum) && lp_print_ok(snum))) {
644                         continue;
645                 }
646
647                 /* ignore [printers] share */
648                 if (strequal(printer, "printers")) {
649                         continue;
650                 }
651
652                 fstrcpy(sname, printer);
653                 if (strequal(aprinter, printer)) {
654                         found = true;
655                         break;
656                 }
657
658                 /* no point looking up the printer object if
659                    we aren't allowing printername != sharename */
660                 if (lp_force_printername(snum)) {
661                         continue;
662                 }
663
664                 result = winreg_get_printer(mem_ctx,
665                                             server_info,
666                                             msg_ctx,
667                                             sname,
668                                             &info2);
669                 if ( !W_ERROR_IS_OK(result) ) {
670                         DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
671                                  sname, win_errstr(result)));
672                         continue;
673                 }
674
675                 printername = strrchr(info2->printername, '\\');
676                 if (printername == NULL) {
677                         printername = info2->printername;
678                 } else {
679                         printername++;
680                 }
681
682                 if (strequal(printername, aprinter)) {
683                         found = true;
684                         break;
685                 }
686
687                 DEBUGADD(10, ("printername: %s\n", printername));
688
689                 TALLOC_FREE(info2);
690         }
691
692         if ( !found ) {
693                 if (cache_key != NULL) {
694                         gencache_set(cache_key, printer_not_found,
695                                      time(NULL)+300);
696                         TALLOC_FREE(cache_key);
697                 }
698                 DEBUGADD(4,("Printer not found\n"));
699                 return false;
700         }
701
702         if (cache_key != NULL) {
703                 gencache_set(cache_key, sname, time(NULL)+300);
704                 TALLOC_FREE(cache_key);
705         }
706
707         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
708
709         fstrcpy(Printer->sharename, sname);
710
711         return true;
712 }
713
714 /****************************************************************************
715  Find first available printer slot. creates a printer handle for you.
716  ****************************************************************************/
717
718 static bool open_printer_hnd(struct pipes_struct *p, struct policy_handle *hnd,
719                              const char *name, uint32_t access_granted)
720 {
721         struct printer_handle *new_printer;
722
723         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
724
725         new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
726         if (new_printer == NULL) {
727                 return false;
728         }
729         talloc_set_destructor(new_printer, printer_entry_destructor);
730
731         /* This also steals the printer_handle on the policy_handle */
732         if (!create_policy_hnd(p, hnd, new_printer)) {
733                 TALLOC_FREE(new_printer);
734                 return false;
735         }
736
737         /* Add to the internal list. */
738         DLIST_ADD(printers_list, new_printer);
739
740         new_printer->notify.option=NULL;
741
742         if (!set_printer_hnd_printertype(new_printer, name)) {
743                 close_printer_handle(p, hnd);
744                 return false;
745         }
746
747         if (!set_printer_hnd_name(p->mem_ctx,
748                                   get_server_info_system(),
749                                   p->msg_ctx,
750                                   new_printer, name)) {
751                 close_printer_handle(p, hnd);
752                 return false;
753         }
754
755         new_printer->access_granted = access_granted;
756
757         DEBUG(5, ("%d printer handles active\n",
758                   (int)num_pipe_handles(p)));
759
760         return true;
761 }
762
763 /***************************************************************************
764  check to see if the client motify handle is monitoring the notification
765  given by (notify_type, notify_field).
766  **************************************************************************/
767
768 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
769                                       uint16_t notify_field)
770 {
771         return true;
772 }
773
774 static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
775                                 uint16_t notify_field)
776 {
777         struct spoolss_NotifyOption *option = p->notify.option;
778         uint32_t i, j;
779
780         /*
781          * Flags should always be zero when the change notify
782          * is registered by the client's spooler.  A user Win32 app
783          * might use the flags though instead of the NOTIFY_OPTION_INFO
784          * --jerry
785          */
786
787         if (!option) {
788                 return false;
789         }
790
791         if (p->notify.flags)
792                 return is_monitoring_event_flags(
793                         p->notify.flags, notify_type, notify_field);
794
795         for (i = 0; i < option->count; i++) {
796
797                 /* Check match for notify_type */
798
799                 if (option->types[i].type != notify_type)
800                         continue;
801
802                 /* Check match for field */
803
804                 for (j = 0; j < option->types[i].count; j++) {
805                         if (option->types[i].fields[j].field == notify_field) {
806                                 return true;
807                         }
808                 }
809         }
810
811         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
812                    p->servername, p->sharename, notify_type, notify_field));
813
814         return false;
815 }
816
817 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
818         _data->data.integer[0] = _integer; \
819         _data->data.integer[1] = 0;
820
821
822 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
823         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
824         if (!_data->data.string.string) {\
825                 _data->data.string.size = 0; \
826         } \
827         _data->data.string.size = strlen_m_term(_p) * 2;
828
829 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
830         _data->data.devmode.devmode = _devmode;
831
832 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
833         _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
834         if (!_data->data.sd.sd) { \
835                 _data->data.sd.sd_size = 0; \
836         } \
837         _data->data.sd.sd_size = \
838                 ndr_size_security_descriptor(_data->data.sd.sd, 0);
839
840 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
841                                    struct tm *t,
842                                    const char **pp,
843                                    uint32_t *plen)
844 {
845         struct spoolss_Time st;
846         uint32_t len = 16;
847         char *p;
848
849         if (!init_systemtime(&st, t)) {
850                 return;
851         }
852
853         p = talloc_array(mem_ctx, char, len);
854         if (!p) {
855                 return;
856         }
857
858         /*
859          * Systemtime must be linearized as a set of UINT16's.
860          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
861          */
862
863         SSVAL(p, 0, st.year);
864         SSVAL(p, 2, st.month);
865         SSVAL(p, 4, st.day_of_week);
866         SSVAL(p, 6, st.day);
867         SSVAL(p, 8, st.hour);
868         SSVAL(p, 10, st.minute);
869         SSVAL(p, 12, st.second);
870         SSVAL(p, 14, st.millisecond);
871
872         *pp = p;
873         *plen = len;
874 }
875
876 /* Convert a notification message to a struct spoolss_Notify */
877
878 static void notify_one_value(struct spoolss_notify_msg *msg,
879                              struct spoolss_Notify *data,
880                              TALLOC_CTX *mem_ctx)
881 {
882         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
883 }
884
885 static void notify_string(struct spoolss_notify_msg *msg,
886                           struct spoolss_Notify *data,
887                           TALLOC_CTX *mem_ctx)
888 {
889         /* The length of the message includes the trailing \0 */
890
891         data->data.string.size = msg->len * 2;
892         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
893         if (!data->data.string.string) {
894                 data->data.string.size = 0;
895                 return;
896         }
897 }
898
899 static void notify_system_time(struct spoolss_notify_msg *msg,
900                                struct spoolss_Notify *data,
901                                TALLOC_CTX *mem_ctx)
902 {
903         data->data.string.string = NULL;
904         data->data.string.size = 0;
905
906         if (msg->len != sizeof(time_t)) {
907                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
908                           msg->len));
909                 return;
910         }
911
912         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
913                                &data->data.string.string,
914                                &data->data.string.size);
915 }
916
917 struct notify2_message_table {
918         const char *name;
919         void (*fn)(struct spoolss_notify_msg *msg,
920                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
921 };
922
923 static struct notify2_message_table printer_notify_table[] = {
924         /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
925         /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
926         /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
927         /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
928         /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
929         /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
930         /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
931         /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
932         /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
933         /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
934         /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
935         /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
936         /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
937         /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
938         /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
939         /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
940         /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
941         /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
942         /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
943 };
944
945 static struct notify2_message_table job_notify_table[] = {
946         /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
947         /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
948         /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
949         /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
950         /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
951         /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
952         /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
953         /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
954         /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
955         /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
956         /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
957         /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
958         /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
959         /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
960         /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
961         /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
962         /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
963         /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
964         /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
965         /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
966         /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
967         /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
968         /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
969         /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
970 };
971
972
973 /***********************************************************************
974  Allocate talloc context for container object
975  **********************************************************************/
976
977 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
978 {
979         if ( !ctr )
980                 return;
981
982         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
983
984         return;
985 }
986
987 /***********************************************************************
988  release all allocated memory and zero out structure
989  **********************************************************************/
990
991 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
992 {
993         if ( !ctr )
994                 return;
995
996         if ( ctr->ctx )
997                 talloc_destroy(ctr->ctx);
998
999         ZERO_STRUCTP(ctr);
1000
1001         return;
1002 }
1003
1004 /***********************************************************************
1005  **********************************************************************/
1006
1007 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1008 {
1009         if ( !ctr )
1010                 return NULL;
1011
1012         return ctr->ctx;
1013 }
1014
1015 /***********************************************************************
1016  **********************************************************************/
1017
1018 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1019 {
1020         if ( !ctr || !ctr->msg_groups )
1021                 return NULL;
1022
1023         if ( idx >= ctr->num_groups )
1024                 return NULL;
1025
1026         return &ctr->msg_groups[idx];
1027
1028 }
1029
1030 /***********************************************************************
1031  How many groups of change messages do we have ?
1032  **********************************************************************/
1033
1034 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1035 {
1036         if ( !ctr )
1037                 return 0;
1038
1039         return ctr->num_groups;
1040 }
1041
1042 /***********************************************************************
1043  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1044  **********************************************************************/
1045
1046 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1047 {
1048         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
1049         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
1050         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
1051         int                             i, new_slot;
1052
1053         if ( !ctr || !msg )
1054                 return 0;
1055
1056         /* loop over all groups looking for a matching printer name */
1057
1058         for ( i=0; i<ctr->num_groups; i++ ) {
1059                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1060                         break;
1061         }
1062
1063         /* add a new group? */
1064
1065         if ( i == ctr->num_groups ) {
1066                 ctr->num_groups++;
1067
1068                 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1069                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1070                         return 0;
1071                 }
1072                 ctr->msg_groups = groups;
1073
1074                 /* clear the new entry and set the printer name */
1075
1076                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1077                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1078         }
1079
1080         /* add the change messages; 'i' is the correct index now regardless */
1081
1082         msg_grp = &ctr->msg_groups[i];
1083
1084         msg_grp->num_msgs++;
1085
1086         if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1087                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1088                 return 0;
1089         }
1090         msg_grp->msgs = msg_list;
1091
1092         new_slot = msg_grp->num_msgs-1;
1093         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1094
1095         /* need to allocate own copy of data */
1096
1097         if ( msg->len != 0 )
1098                 msg_grp->msgs[new_slot].notify.data = (char *)
1099                         TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
1100
1101         return ctr->num_groups;
1102 }
1103
1104 static void construct_info_data(struct spoolss_Notify *info_data,
1105                                 enum spoolss_NotifyType type,
1106                                 uint16_t field, int id);
1107
1108 /***********************************************************************
1109  Send a change notication message on all handles which have a call
1110  back registered
1111  **********************************************************************/
1112
1113 static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1114                                   struct printer_handle *prn_hnd,
1115                                   SPOOLSS_NOTIFY_MSG *messages,
1116                                   uint32_t num_msgs,
1117                                   struct spoolss_Notify **_notifies,
1118                                   int *_count)
1119 {
1120         struct spoolss_Notify *notifies;
1121         SPOOLSS_NOTIFY_MSG *msg;
1122         int count = 0;
1123         uint32_t id;
1124         int i;
1125
1126         notifies = talloc_zero_array(mem_ctx,
1127                                      struct spoolss_Notify, num_msgs);
1128         if (!notifies) {
1129                 return ENOMEM;
1130         }
1131
1132         for (i = 0; i < num_msgs; i++) {
1133
1134                 msg = &messages[i];
1135
1136                 /* Are we monitoring this event? */
1137
1138                 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1139                         continue;
1140                 }
1141
1142                 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1143                            "for printer [%s]\n",
1144                            msg->type, msg->field, prn_hnd->sharename));
1145
1146                 /*
1147                  * if the is a printer notification handle and not a job
1148                  * notification type, then set the id to 0.
1149                  * Otherwise just use what was specified in the message.
1150                  *
1151                  * When registering change notification on a print server
1152                  * handle we always need to send back the id (snum) matching
1153                  * the printer for which the change took place.
1154                  * For change notify registered on a printer handle,
1155                  * this does not matter and the id should be 0.
1156                  *
1157                  * --jerry
1158                  */
1159
1160                 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1161                     (prn_hnd->printer_type == SPLHND_PRINTER)) {
1162                         id = 0;
1163                 } else {
1164                         id = msg->id;
1165                 }
1166
1167                 /* Convert unix jobid to smb jobid */
1168
1169                 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1170                         id = sysjob_to_jobid(msg->id);
1171
1172                         if (id == -1) {
1173                                 DEBUG(3, ("no such unix jobid %d\n",
1174                                           msg->id));
1175                                 continue;
1176                         }
1177                 }
1178
1179                 construct_info_data(&notifies[count],
1180                                     msg->type, msg->field, id);
1181
1182                 switch(msg->type) {
1183                 case PRINTER_NOTIFY_TYPE:
1184                         if (printer_notify_table[msg->field].fn) {
1185                                 printer_notify_table[msg->field].fn(msg,
1186                                                 &notifies[count], mem_ctx);
1187                         }
1188                         break;
1189
1190                 case JOB_NOTIFY_TYPE:
1191                         if (job_notify_table[msg->field].fn) {
1192                                 job_notify_table[msg->field].fn(msg,
1193                                                 &notifies[count], mem_ctx);
1194                         }
1195                         break;
1196
1197                 default:
1198                         DEBUG(5, ("Unknown notification type %d\n",
1199                                   msg->type));
1200                         continue;
1201                 }
1202
1203                 count++;
1204         }
1205
1206         *_notifies = notifies;
1207         *_count = count;
1208
1209         return 0;
1210 }
1211
1212 static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1213                                 struct printer_handle *prn_hnd,
1214                                 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1215 {
1216         struct spoolss_Notify *notifies;
1217         int count = 0;
1218         union spoolss_ReplyPrinterInfo info;
1219         struct spoolss_NotifyInfo info0;
1220         uint32_t reply_result;
1221         NTSTATUS status;
1222         WERROR werr;
1223         int ret;
1224
1225         /* Is there notification on this handle? */
1226         if (prn_hnd->notify.cli_chan == NULL ||
1227             prn_hnd->notify.cli_chan->active_connections == 0) {
1228                 return 0;
1229         }
1230
1231         DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1232                    prn_hnd->servername, prn_hnd->sharename));
1233
1234         /* For this printer? Print servers always receive notifications. */
1235         if ((prn_hnd->printer_type == SPLHND_PRINTER)  &&
1236             (!strequal(msg_group->printername, prn_hnd->sharename))) {
1237                 return 0;
1238         }
1239
1240         DEBUG(10,("Our printer\n"));
1241
1242         /* build the array of change notifications */
1243         ret = build_notify2_messages(mem_ctx, prn_hnd,
1244                                      msg_group->msgs,
1245                                      msg_group->num_msgs,
1246                                      &notifies, &count);
1247         if (ret) {
1248                 return ret;
1249         }
1250
1251         info0.version   = 0x2;
1252         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1253         info0.count     = count;
1254         info0.notifies  = notifies;
1255
1256         info.info0 = &info0;
1257
1258         status = rpccli_spoolss_RouterReplyPrinterEx(
1259                                 prn_hnd->notify.cli_chan->cli_pipe,
1260                                 mem_ctx,
1261                                 &prn_hnd->notify.cli_hnd,
1262                                 prn_hnd->notify.change, /* color */
1263                                 prn_hnd->notify.flags,
1264                                 &reply_result,
1265                                 0, /* reply_type, must be 0 */
1266                                 info, &werr);
1267         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr)) {
1268                 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1269                           "failed: %s\n",
1270                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1271                           win_errstr(werr)));
1272         }
1273         switch (reply_result) {
1274         case 0:
1275                 break;
1276         case PRINTER_NOTIFY_INFO_DISCARDED:
1277         case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1278         case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1279                 break;
1280         default:
1281                 break;
1282         }
1283
1284         return 0;
1285 }
1286
1287 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1288 {
1289         struct printer_handle    *p;
1290         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
1291         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1292         int ret;
1293
1294         if ( !msg_group ) {
1295                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1296                 return;
1297         }
1298
1299         if (!msg_group->msgs) {
1300                 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1301                 return;
1302         }
1303
1304         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1305
1306         /* loop over all printers */
1307
1308         for (p = printers_list; p; p = p->next) {
1309                 ret = send_notify2_printer(mem_ctx, p, msg_group);
1310                 if (ret) {
1311                         goto done;
1312                 }
1313         }
1314
1315 done:
1316         DEBUG(8,("send_notify2_changes: Exit...\n"));
1317         return;
1318 }
1319
1320 /***********************************************************************
1321  **********************************************************************/
1322
1323 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1324 {
1325
1326         uint32_t tv_sec, tv_usec;
1327         size_t offset = 0;
1328
1329         /* Unpack message */
1330
1331         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1332                              msg->printer);
1333
1334         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1335                                 &tv_sec, &tv_usec,
1336                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1337
1338         if (msg->len == 0)
1339                 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1340                            &msg->notify.value[0], &msg->notify.value[1]);
1341         else
1342                 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1343                            &msg->len, &msg->notify.data);
1344
1345         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1346                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1347
1348         tv->tv_sec = tv_sec;
1349         tv->tv_usec = tv_usec;
1350
1351         if (msg->len == 0)
1352                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1353                           msg->notify.value[1]));
1354         else
1355                 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1356
1357         return true;
1358 }
1359
1360 /********************************************************************
1361  Receive a notify2 message list
1362  ********************************************************************/
1363
1364 static void receive_notify2_message_list(struct messaging_context *msg,
1365                                          void *private_data,
1366                                          uint32_t msg_type,
1367                                          struct server_id server_id,
1368                                          DATA_BLOB *data)
1369 {
1370         size_t                  msg_count, i;
1371         char                    *buf = (char *)data->data;
1372         char                    *msg_ptr;
1373         size_t                  msg_len;
1374         SPOOLSS_NOTIFY_MSG      notify;
1375         SPOOLSS_NOTIFY_MSG_CTR  messages;
1376         int                     num_groups;
1377
1378         if (data->length < 4) {
1379                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1380                 return;
1381         }
1382
1383         msg_count = IVAL(buf, 0);
1384         msg_ptr = buf + 4;
1385
1386         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1387
1388         if (msg_count == 0) {
1389                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1390                 return;
1391         }
1392
1393         /* initialize the container */
1394
1395         ZERO_STRUCT( messages );
1396         notify_msg_ctr_init( &messages );
1397
1398         /*
1399          * build message groups for each printer identified
1400          * in a change_notify msg.  Remember that a PCN message
1401          * includes the handle returned for the srv_spoolss_replyopenprinter()
1402          * call.  Therefore messages are grouped according to printer handle.
1403          */
1404
1405         for ( i=0; i<msg_count; i++ ) {
1406                 struct timeval msg_tv;
1407
1408                 if (msg_ptr + 4 - buf > data->length) {
1409                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1410                         return;
1411                 }
1412
1413                 msg_len = IVAL(msg_ptr,0);
1414                 msg_ptr += 4;
1415
1416                 if (msg_ptr + msg_len - buf > data->length) {
1417                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1418                         return;
1419                 }
1420
1421                 /* unpack messages */
1422
1423                 ZERO_STRUCT( notify );
1424                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1425                 msg_ptr += msg_len;
1426
1427                 /* add to correct list in container */
1428
1429                 notify_msg_ctr_addmsg( &messages, &notify );
1430
1431                 /* free memory that might have been allocated by notify2_unpack_msg() */
1432
1433                 if ( notify.len != 0 )
1434                         SAFE_FREE( notify.notify.data );
1435         }
1436
1437         /* process each group of messages */
1438
1439         num_groups = notify_msg_ctr_numgroups( &messages );
1440         for ( i=0; i<num_groups; i++ )
1441                 send_notify2_changes( &messages, i );
1442
1443
1444         /* cleanup */
1445
1446         DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1447                 (uint32_t)msg_count ));
1448
1449         notify_msg_ctr_destroy( &messages );
1450
1451         return;
1452 }
1453
1454 /********************************************************************
1455  Send a message to ourself about new driver being installed
1456  so we can upgrade the information for each printer bound to this
1457  driver
1458  ********************************************************************/
1459
1460 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1461                                             struct messaging_context *msg_ctx)
1462 {
1463         int len = strlen(drivername);
1464
1465         if (!len)
1466                 return false;
1467
1468         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1469                 drivername));
1470
1471         messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1472                            MSG_PRINTER_DRVUPGRADE,
1473                            (uint8_t *)drivername, len+1);
1474
1475         return true;
1476 }
1477
1478 void srv_spoolss_cleanup(void)
1479 {
1480         struct printer_session_counter *session_counter;
1481
1482         for (session_counter = counter_list;
1483              session_counter != NULL;
1484              session_counter = counter_list) {
1485                 DLIST_REMOVE(counter_list, session_counter);
1486                 TALLOC_FREE(session_counter);
1487         }
1488 }
1489
1490 /**********************************************************************
1491  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1492  over all printers, upgrading ones as necessary
1493  **********************************************************************/
1494
1495 void do_drv_upgrade_printer(struct messaging_context *msg,
1496                             void *private_data,
1497                             uint32_t msg_type,
1498                             struct server_id server_id,
1499                             DATA_BLOB *data)
1500 {
1501         TALLOC_CTX *tmp_ctx;
1502         struct auth_serversupplied_info *server_info = NULL;
1503         struct spoolss_PrinterInfo2 *pinfo2;
1504         NTSTATUS status;
1505         WERROR result;
1506         const char *drivername;
1507         int snum;
1508         int n_services = lp_numservices();
1509
1510         tmp_ctx = talloc_new(NULL);
1511         if (!tmp_ctx) return;
1512
1513         status = make_server_info_system(tmp_ctx, &server_info);
1514         if (!NT_STATUS_IS_OK(status)) {
1515                 DEBUG(0, ("do_drv_upgrade_printer: "
1516                           "Could not create system server_info\n"));
1517                 goto done;
1518         }
1519
1520         drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1521         if (!drivername) {
1522                 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1523                 goto done;
1524         }
1525
1526         DEBUG(10, ("do_drv_upgrade_printer: "
1527                    "Got message for new driver [%s]\n", drivername));
1528
1529         /* Iterate the printer list */
1530
1531         for (snum = 0; snum < n_services; snum++) {
1532                 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1533                         continue;
1534                 }
1535
1536                 /* ignore [printers] share */
1537                 if (strequal(lp_const_servicename(snum), "printers")) {
1538                         continue;
1539                 }
1540
1541                 result = winreg_get_printer(tmp_ctx, server_info, msg,
1542                                             lp_const_servicename(snum),
1543                                             &pinfo2);
1544
1545                 if (!W_ERROR_IS_OK(result)) {
1546                         continue;
1547                 }
1548
1549                 if (!pinfo2->drivername) {
1550                         continue;
1551                 }
1552
1553                 if (strcmp(drivername, pinfo2->drivername) != 0) {
1554                         continue;
1555                 }
1556
1557                 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1558
1559                 /* all we care about currently is the change_id */
1560                 result = winreg_printer_update_changeid(tmp_ctx,
1561                                                         server_info,
1562                                                         msg,
1563                                                         pinfo2->printername);
1564
1565                 if (!W_ERROR_IS_OK(result)) {
1566                         DEBUG(3, ("do_drv_upgrade_printer: "
1567                                   "Failed to update changeid [%s]\n",
1568                                   win_errstr(result)));
1569                 }
1570         }
1571
1572         /* all done */
1573 done:
1574         talloc_free(tmp_ctx);
1575 }
1576
1577 /********************************************************************
1578  Update the cache for all printq's with a registered client
1579  connection
1580  ********************************************************************/
1581
1582 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1583 {
1584         struct printer_handle *printer = printers_list;
1585         int snum;
1586
1587         /* loop through all printers and update the cache where
1588            a client is connected */
1589         while (printer) {
1590                 if ((printer->printer_type == SPLHND_PRINTER) &&
1591                     ((printer->notify.cli_chan != NULL) &&
1592                      (printer->notify.cli_chan->active_connections > 0))) {
1593                         snum = print_queue_snum(printer->sharename);
1594                         print_queue_status(msg_ctx, snum, NULL, NULL);
1595                 }
1596
1597                 printer = printer->next;
1598         }
1599
1600         return;
1601 }
1602
1603 /****************************************************************
1604  _spoolss_OpenPrinter
1605 ****************************************************************/
1606
1607 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1608                             struct spoolss_OpenPrinter *r)
1609 {
1610         struct spoolss_OpenPrinterEx e;
1611         WERROR werr;
1612
1613         ZERO_STRUCT(e.in.userlevel);
1614
1615         e.in.printername        = r->in.printername;
1616         e.in.datatype           = r->in.datatype;
1617         e.in.devmode_ctr        = r->in.devmode_ctr;
1618         e.in.access_mask        = r->in.access_mask;
1619         e.in.level              = 0;
1620
1621         e.out.handle            = r->out.handle;
1622
1623         werr = _spoolss_OpenPrinterEx(p, &e);
1624
1625         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1626                 /* OpenPrinterEx returns this for a bad
1627                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1628                  * instead.
1629                  */
1630                 werr = WERR_INVALID_PRINTER_NAME;
1631         }
1632
1633         return werr;
1634 }
1635
1636 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1637                               struct spoolss_DeviceMode *orig,
1638                               struct spoolss_DeviceMode **dest)
1639 {
1640         struct spoolss_DeviceMode *dm;
1641
1642         dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1643         if (!dm) {
1644                 return WERR_NOMEM;
1645         }
1646
1647         /* copy all values, then duplicate strings and structs */
1648         *dm = *orig;
1649
1650         dm->devicename = talloc_strdup(dm, orig->devicename);
1651         if (!dm->devicename) {
1652                 return WERR_NOMEM;
1653         }
1654         dm->formname = talloc_strdup(dm, orig->formname);
1655         if (!dm->formname) {
1656                 return WERR_NOMEM;
1657         }
1658         if (orig->driverextra_data.data) {
1659                 dm->driverextra_data.data =
1660                         (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1661                                         orig->driverextra_data.length);
1662                 if (!dm->driverextra_data.data) {
1663                         return WERR_NOMEM;
1664                 }
1665         }
1666
1667         *dest = dm;
1668         return WERR_OK;
1669 }
1670
1671 /****************************************************************
1672  _spoolss_OpenPrinterEx
1673 ****************************************************************/
1674
1675 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1676                               struct spoolss_OpenPrinterEx *r)
1677 {
1678         int snum;
1679         struct printer_handle *Printer=NULL;
1680
1681         if (!r->in.printername) {
1682                 return WERR_INVALID_PARAM;
1683         }
1684
1685         /* some sanity check because you can open a printer or a print server */
1686         /* aka: \\server\printer or \\server */
1687
1688         DEBUGADD(3,("checking name: %s\n", r->in.printername));
1689
1690         if (!open_printer_hnd(p, r->out.handle, r->in.printername, 0)) {
1691                 DEBUG(0,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1692                         "for printer %s\n", r->in.printername));
1693                 ZERO_STRUCTP(r->out.handle);
1694                 return WERR_INVALID_PARAM;
1695         }
1696
1697         Printer = find_printer_index_by_hnd(p, r->out.handle);
1698         if ( !Printer ) {
1699                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1700                         "handle we created for printer %s\n", r->in.printername));
1701                 close_printer_handle(p, r->out.handle);
1702                 ZERO_STRUCTP(r->out.handle);
1703                 return WERR_INVALID_PARAM;
1704         }
1705
1706         /*
1707          * First case: the user is opening the print server:
1708          *
1709          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1710          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1711          *
1712          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1713          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1714          * or if the user is listed in the smb.conf printer admin parameter.
1715          *
1716          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1717          * client view printer folder, but does not show the MSAPW.
1718          *
1719          * Note: this test needs code to check access rights here too. Jeremy
1720          * could you look at this?
1721          *
1722          * Second case: the user is opening a printer:
1723          * NT doesn't let us connect to a printer if the connecting user
1724          * doesn't have print permission.
1725          *
1726          * Third case: user is opening a Port Monitor
1727          * access checks same as opening a handle to the print server.
1728          */
1729
1730         switch (Printer->printer_type )
1731         {
1732         case SPLHND_SERVER:
1733         case SPLHND_PORTMON_TCP:
1734         case SPLHND_PORTMON_LOCAL:
1735                 /* Printserver handles use global struct... */
1736
1737                 snum = -1;
1738
1739                 /* Map standard access rights to object specific access rights */
1740
1741                 se_map_standard(&r->in.access_mask,
1742                                 &printserver_std_mapping);
1743
1744                 /* Deny any object specific bits that don't apply to print
1745                    servers (i.e printer and job specific bits) */
1746
1747                 r->in.access_mask &= SEC_MASK_SPECIFIC;
1748
1749                 if (r->in.access_mask &
1750                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1751                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1752                         close_printer_handle(p, r->out.handle);
1753                         ZERO_STRUCTP(r->out.handle);
1754                         return WERR_ACCESS_DENIED;
1755                 }
1756
1757                 /* Allow admin access */
1758
1759                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1760                 {
1761                         if (!lp_ms_add_printer_wizard()) {
1762                                 close_printer_handle(p, r->out.handle);
1763                                 ZERO_STRUCTP(r->out.handle);
1764                                 return WERR_ACCESS_DENIED;
1765                         }
1766
1767                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1768                            and not a printer admin, then fail */
1769
1770                         if ((p->server_info->utok.uid != sec_initial_uid()) &&
1771                             !security_token_has_privilege(p->server_info->ptok, SEC_PRIV_PRINT_OPERATOR) &&
1772                             !token_contains_name_in_list(
1773                                     uidtoname(p->server_info->utok.uid),
1774                                     p->server_info->info3->base.domain.string,
1775                                     NULL,
1776                                     p->server_info->ptok,
1777                                     lp_printer_admin(snum))) {
1778                                 close_printer_handle(p, r->out.handle);
1779                                 ZERO_STRUCTP(r->out.handle);
1780                                 return WERR_ACCESS_DENIED;
1781                         }
1782
1783                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1784                 }
1785                 else
1786                 {
1787                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1788                 }
1789
1790                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1791                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1792
1793                 /* We fall through to return WERR_OK */
1794                 break;
1795
1796         case SPLHND_PRINTER:
1797                 /* NT doesn't let us connect to a printer if the connecting user
1798                    doesn't have print permission.  */
1799
1800                 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1801                         close_printer_handle(p, r->out.handle);
1802                         ZERO_STRUCTP(r->out.handle);
1803                         return WERR_BADFID;
1804                 }
1805
1806                 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1807                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1808                 }
1809
1810                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1811
1812                 /* map an empty access mask to the minimum access mask */
1813                 if (r->in.access_mask == 0x0)
1814                         r->in.access_mask = PRINTER_ACCESS_USE;
1815
1816                 /*
1817                  * If we are not serving the printer driver for this printer,
1818                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1819                  * will keep NT clients happy  --jerry
1820                  */
1821
1822                 if (lp_use_client_driver(snum)
1823                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1824                 {
1825                         r->in.access_mask = PRINTER_ACCESS_USE;
1826                 }
1827
1828                 /* check smb.conf parameters and the the sec_desc */
1829
1830                 if (!allow_access(lp_hostsdeny(snum), lp_hostsallow(snum),
1831                                   p->client_id->name, p->client_id->addr)) {
1832                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1833                         ZERO_STRUCTP(r->out.handle);
1834                         return WERR_ACCESS_DENIED;
1835                 }
1836
1837                 if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
1838                                    p->server_info->ptok, snum) ||
1839                     !print_access_check(p->server_info,
1840                                         p->msg_ctx,
1841                                         snum,
1842                                         r->in.access_mask)) {
1843                         DEBUG(3, ("access DENIED for printer open\n"));
1844                         close_printer_handle(p, r->out.handle);
1845                         ZERO_STRUCTP(r->out.handle);
1846                         return WERR_ACCESS_DENIED;
1847                 }
1848
1849                 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1850                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1851                         close_printer_handle(p, r->out.handle);
1852                         ZERO_STRUCTP(r->out.handle);
1853                         return WERR_ACCESS_DENIED;
1854                 }
1855
1856                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1857                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1858                 else
1859                         r->in.access_mask = PRINTER_ACCESS_USE;
1860
1861                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1862                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1863
1864                 winreg_create_printer(p->mem_ctx,
1865                                       get_server_info_system(),
1866                                       p->msg_ctx,
1867                                       lp_const_servicename(snum));
1868
1869                 break;
1870
1871         default:
1872                 /* sanity check to prevent programmer error */
1873                 ZERO_STRUCTP(r->out.handle);
1874                 return WERR_BADFID;
1875         }
1876
1877         Printer->access_granted = r->in.access_mask;
1878
1879         /*
1880          * If the client sent a devmode in the OpenPrinter() call, then
1881          * save it here in case we get a job submission on this handle
1882          */
1883
1884          if ((Printer->printer_type != SPLHND_SERVER) &&
1885              r->in.devmode_ctr.devmode) {
1886                 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1887                                 &Printer->devmode);
1888          }
1889
1890 #if 0   /* JERRY -- I'm doubtful this is really effective */
1891         /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1892            optimization in Windows 2000 clients  --jerry */
1893
1894         if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1895                 && (RA_WIN2K == get_remote_arch()) )
1896         {
1897                 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1898                 sys_usleep( 500000 );
1899         }
1900 #endif
1901
1902         return WERR_OK;
1903 }
1904
1905 /****************************************************************
1906  _spoolss_ClosePrinter
1907 ****************************************************************/
1908
1909 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1910                              struct spoolss_ClosePrinter *r)
1911 {
1912         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1913
1914         if (Printer && Printer->document_started) {
1915                 struct spoolss_EndDocPrinter e;
1916
1917                 e.in.handle = r->in.handle;
1918
1919                 _spoolss_EndDocPrinter(p, &e);
1920         }
1921
1922         if (!close_printer_handle(p, r->in.handle))
1923                 return WERR_BADFID;
1924
1925         /* clear the returned printer handle.  Observed behavior
1926            from Win2k server.  Don't think this really matters.
1927            Previous code just copied the value of the closed
1928            handle.    --jerry */
1929
1930         ZERO_STRUCTP(r->out.handle);
1931
1932         return WERR_OK;
1933 }
1934
1935 /****************************************************************
1936  _spoolss_DeletePrinter
1937 ****************************************************************/
1938
1939 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
1940                               struct spoolss_DeletePrinter *r)
1941 {
1942         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1943         WERROR result;
1944         int snum;
1945
1946         if (Printer && Printer->document_started) {
1947                 struct spoolss_EndDocPrinter e;
1948
1949                 e.in.handle = r->in.handle;
1950
1951                 _spoolss_EndDocPrinter(p, &e);
1952         }
1953
1954         if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
1955                 winreg_delete_printer_key(p->mem_ctx,
1956                                           get_server_info_system(),
1957                                           p->msg_ctx,
1958                                           lp_const_servicename(snum),
1959                                           "");
1960         }
1961
1962         result = delete_printer_handle(p, r->in.handle);
1963
1964         return result;
1965 }
1966
1967 /*******************************************************************
1968  * static function to lookup the version id corresponding to an
1969  * long architecture string
1970  ******************************************************************/
1971
1972 static const struct print_architecture_table_node archi_table[]= {
1973
1974         {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
1975         {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
1976         {"Windows NT R4000",     SPL_ARCH_W32MIPS,      2 },
1977         {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,     2 },
1978         {"Windows NT PowerPC",   SPL_ARCH_W32PPC,       2 },
1979         {"Windows IA64",         SPL_ARCH_IA64,         3 },
1980         {"Windows x64",          SPL_ARCH_X64,          3 },
1981         {NULL,                   "",            -1 }
1982 };
1983
1984 static int get_version_id(const char *arch)
1985 {
1986         int i;
1987
1988         for (i=0; archi_table[i].long_archi != NULL; i++)
1989         {
1990                 if (strcmp(arch, archi_table[i].long_archi) == 0)
1991                         return (archi_table[i].version);
1992         }
1993
1994         return -1;
1995 }
1996
1997 /****************************************************************
1998  _spoolss_DeletePrinterDriver
1999 ****************************************************************/
2000
2001 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2002                                     struct spoolss_DeletePrinterDriver *r)
2003 {
2004
2005         struct spoolss_DriverInfo8 *info = NULL;
2006         struct spoolss_DriverInfo8 *info_win2k = NULL;
2007         int                             version;
2008         WERROR                          status;
2009
2010         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2011            and not a printer admin, then fail */
2012
2013         if ( (p->server_info->utok.uid != sec_initial_uid())
2014              && !security_token_has_privilege(p->server_info->ptok, SEC_PRIV_PRINT_OPERATOR)
2015                 && !token_contains_name_in_list(
2016                         uidtoname(p->server_info->utok.uid),
2017                         p->server_info->info3->base.domain.string,
2018                         NULL,
2019                         p->server_info->ptok,
2020                         lp_printer_admin(-1)) )
2021         {
2022                 return WERR_ACCESS_DENIED;
2023         }
2024
2025         /* check that we have a valid driver name first */
2026
2027         if ((version = get_version_id(r->in.architecture)) == -1)
2028                 return WERR_INVALID_ENVIRONMENT;
2029
2030         status = winreg_get_driver(p->mem_ctx,
2031                                    get_server_info_system(),
2032                                    p->msg_ctx,
2033                                    r->in.architecture, r->in.driver,
2034                                    version, &info);
2035         if (!W_ERROR_IS_OK(status)) {
2036                 /* try for Win2k driver if "Windows NT x86" */
2037
2038                 if ( version == 2 ) {
2039                         version = 3;
2040
2041                         status = winreg_get_driver(p->mem_ctx,
2042                                                    get_server_info_system(),
2043                                                    p->msg_ctx,
2044                                                    r->in.architecture,
2045                                                    r->in.driver,
2046                                                    version, &info);
2047                         if (!W_ERROR_IS_OK(status)) {
2048                                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2049                                 goto done;
2050                         }
2051                 }
2052                 /* otherwise it was a failure */
2053                 else {
2054                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2055                         goto done;
2056                 }
2057
2058         }
2059
2060         if (printer_driver_in_use(p->mem_ctx,
2061                                   get_server_info_system(),
2062                                   p->msg_ctx,
2063                                   info)) {
2064                 status = WERR_PRINTER_DRIVER_IN_USE;
2065                 goto done;
2066         }
2067
2068         if (version == 2) {
2069                 status = winreg_get_driver(p->mem_ctx,
2070                                            get_server_info_system(),
2071                                            p->msg_ctx,
2072                                            r->in.architecture,
2073                                            r->in.driver, 3, &info_win2k);
2074                 if (W_ERROR_IS_OK(status)) {
2075                         /* if we get to here, we now have 2 driver info structures to remove */
2076                         /* remove the Win2k driver first*/
2077
2078                         status = winreg_del_driver(p->mem_ctx,
2079                                                    get_server_info_system(),
2080                                                    p->msg_ctx,
2081                                                    info_win2k, 3);
2082                         talloc_free(info_win2k);
2083
2084                         /* this should not have failed---if it did, report to client */
2085                         if (!W_ERROR_IS_OK(status)) {
2086                                 goto done;
2087                         }
2088                 }
2089         }
2090
2091         status = winreg_del_driver(p->mem_ctx,
2092                                    get_server_info_system(),
2093                                    p->msg_ctx,
2094                                    info, version);
2095
2096 done:
2097         talloc_free(info);
2098
2099         return status;
2100 }
2101
2102 /****************************************************************
2103  _spoolss_DeletePrinterDriverEx
2104 ****************************************************************/
2105
2106 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2107                                       struct spoolss_DeletePrinterDriverEx *r)
2108 {
2109         struct spoolss_DriverInfo8      *info = NULL;
2110         struct spoolss_DriverInfo8      *info_win2k = NULL;
2111         int                             version;
2112         bool                            delete_files;
2113         WERROR                          status;
2114
2115         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2116            and not a printer admin, then fail */
2117
2118         if ( (p->server_info->utok.uid != sec_initial_uid())
2119                 && !security_token_has_privilege(p->server_info->ptok, SEC_PRIV_PRINT_OPERATOR)
2120                 && !token_contains_name_in_list(
2121                         uidtoname(p->server_info->utok.uid),
2122                         p->server_info->info3->base.domain.string,
2123                         NULL,
2124                         p->server_info->ptok, lp_printer_admin(-1)) )
2125         {
2126                 return WERR_ACCESS_DENIED;
2127         }
2128
2129         /* check that we have a valid driver name first */
2130         if ((version = get_version_id(r->in.architecture)) == -1) {
2131                 /* this is what NT returns */
2132                 return WERR_INVALID_ENVIRONMENT;
2133         }
2134
2135         if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2136                 version = r->in.version;
2137
2138         status = winreg_get_driver(p->mem_ctx,
2139                                    get_server_info_system(),
2140                                    p->msg_ctx,
2141                                    r->in.architecture,
2142                                    r->in.driver,
2143                                    version,
2144                                    &info);
2145         if (!W_ERROR_IS_OK(status)) {
2146                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2147
2148                 /*
2149                  * if the client asked for a specific version,
2150                  * or this is something other than Windows NT x86,
2151                  * then we've failed
2152                  */
2153
2154                 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2155                         goto done;
2156
2157                 /* try for Win2k driver if "Windows NT x86" */
2158
2159                 version = 3;
2160                 status = winreg_get_driver(info,
2161                                            get_server_info_system(),
2162                                            p->msg_ctx,
2163                                            r->in.architecture,
2164                                            r->in.driver,
2165                                            version, &info);
2166                 if (!W_ERROR_IS_OK(status)) {
2167                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2168                         goto done;
2169                 }
2170         }
2171
2172         if (printer_driver_in_use(info,
2173                                   get_server_info_system(),
2174                                   p->msg_ctx,
2175                                   info)) {
2176                 status = WERR_PRINTER_DRIVER_IN_USE;
2177                 goto done;
2178         }
2179
2180         /*
2181          * we have a couple of cases to consider.
2182          * (1) Are any files in use?  If so and DPD_DELTE_ALL_FILE is set,
2183          *     then the delete should fail if **any** files overlap with
2184          *     other drivers
2185          * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2186          *     non-overlapping files
2187          * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2188          *     is set, the do not delete any files
2189          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2190          */
2191
2192         delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2193
2194         /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2195
2196         if (delete_files &&
2197             (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2198             printer_driver_files_in_use(info,
2199                                         get_server_info_system(),
2200                                         p->msg_ctx,
2201                                         info)) {
2202                 /* no idea of the correct error here */
2203                 status = WERR_ACCESS_DENIED;
2204                 goto done;
2205         }
2206
2207
2208         /* also check for W32X86/3 if necessary; maybe we already have? */
2209
2210         if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION)  ) {
2211                 status = winreg_get_driver(info,
2212                                            get_server_info_system(),
2213                                            p->msg_ctx,
2214                                            r->in.architecture,
2215                                            r->in.driver, 3, &info_win2k);
2216                 if (W_ERROR_IS_OK(status)) {
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_win2k)) {
2224                                 /* no idea of the correct error here */
2225                                 talloc_free(info_win2k);
2226                                 status = WERR_ACCESS_DENIED;
2227                                 goto done;
2228                         }
2229
2230                         /* if we get to here, we now have 2 driver info structures to remove */
2231                         /* remove the Win2k driver first*/
2232
2233                         status = winreg_del_driver(info,
2234                                                    get_server_info_system(),
2235                                                    p->msg_ctx,
2236                                                    info_win2k,
2237                                                    3);
2238
2239                         /* this should not have failed---if it did, report to client */
2240
2241                         if (!W_ERROR_IS_OK(status)) {
2242                                 goto done;
2243                         }
2244
2245                         /*
2246                          * now delete any associated files if delete_files is
2247                          * true. Even if this part failes, we return succes
2248                          * because the driver doesn not exist any more
2249                          */
2250                         if (delete_files) {
2251                                 delete_driver_files(get_server_info_system(),
2252                                                     info_win2k);
2253                         }
2254                 }
2255         }
2256
2257         status = winreg_del_driver(info,
2258                                    get_server_info_system(),
2259                                    p->msg_ctx,
2260                                    info,
2261                                    version);
2262         if (!W_ERROR_IS_OK(status)) {
2263                 goto done;
2264         }
2265
2266         /*
2267          * now delete any associated files if delete_files is
2268          * true. Even if this part failes, we return succes
2269          * because the driver doesn not exist any more
2270          */
2271         if (delete_files) {
2272                 delete_driver_files(get_server_info_system(), info);
2273         }
2274
2275 done:
2276         talloc_free(info);
2277         return status;
2278 }
2279
2280
2281 /********************************************************************
2282  GetPrinterData on a printer server Handle.
2283 ********************************************************************/
2284
2285 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2286                                             const char *value,
2287                                             enum winreg_Type *type,
2288                                             union spoolss_PrinterData *data)
2289 {
2290         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2291
2292         if (!StrCaseCmp(value, "W3SvcInstalled")) {
2293                 *type = REG_DWORD;
2294                 data->value = 0x00;
2295                 return WERR_OK;
2296         }
2297
2298         if (!StrCaseCmp(value, "BeepEnabled")) {
2299                 *type = REG_DWORD;
2300                 data->value = 0x00;
2301                 return WERR_OK;
2302         }
2303
2304         if (!StrCaseCmp(value, "EventLog")) {
2305                 *type = REG_DWORD;
2306                 /* formally was 0x1b */
2307                 data->value = 0x00;
2308                 return WERR_OK;
2309         }
2310
2311         if (!StrCaseCmp(value, "NetPopup")) {
2312                 *type = REG_DWORD;
2313                 data->value = 0x00;
2314                 return WERR_OK;
2315         }
2316
2317         if (!StrCaseCmp(value, "MajorVersion")) {
2318                 *type = REG_DWORD;
2319
2320                 /* Windows NT 4.0 seems to not allow uploading of drivers
2321                    to a server that reports 0x3 as the MajorVersion.
2322                    need to investigate more how Win2k gets around this .
2323                    -- jerry */
2324
2325                 if (RA_WINNT == get_remote_arch()) {
2326                         data->value = 0x02;
2327                 } else {
2328                         data->value = 0x03;
2329                 }
2330
2331                 return WERR_OK;
2332         }
2333
2334         if (!StrCaseCmp(value, "MinorVersion")) {
2335                 *type = REG_DWORD;
2336                 data->value = 0x00;
2337                 return WERR_OK;
2338         }
2339
2340         /* REG_BINARY
2341          *  uint32_t size        = 0x114
2342          *  uint32_t major       = 5
2343          *  uint32_t minor       = [0|1]
2344          *  uint32_t build       = [2195|2600]
2345          *  extra unicode string = e.g. "Service Pack 3"
2346          */
2347         if (!StrCaseCmp(value, "OSVersion")) {
2348                 DATA_BLOB blob;
2349                 enum ndr_err_code ndr_err;
2350                 struct spoolss_OSVersion os;
2351
2352                 os.major                = 5;    /* Windows 2000 == 5.0 */
2353                 os.minor                = 0;
2354                 os.build                = 2195; /* build */
2355                 os.extra_string         = "";   /* leave extra string empty */
2356
2357                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2358                         (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2359                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2360                         return WERR_GENERAL_FAILURE;
2361                 }
2362
2363                 *type = REG_BINARY;
2364                 data->binary = blob;
2365
2366                 return WERR_OK;
2367         }
2368
2369
2370         if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2371                 *type = REG_SZ;
2372
2373                 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2374                 W_ERROR_HAVE_NO_MEMORY(data->string);
2375
2376                 return WERR_OK;
2377         }
2378
2379         if (!StrCaseCmp(value, "Architecture")) {
2380                 *type = REG_SZ;
2381                 data->string = talloc_strdup(mem_ctx,
2382                         lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2383                 W_ERROR_HAVE_NO_MEMORY(data->string);
2384
2385                 return WERR_OK;
2386         }
2387
2388         if (!StrCaseCmp(value, "DsPresent")) {
2389                 *type = REG_DWORD;
2390
2391                 /* only show the publish check box if we are a
2392                    member of a AD domain */
2393
2394                 if (lp_security() == SEC_ADS) {
2395                         data->value = 0x01;
2396                 } else {
2397                         data->value = 0x00;
2398                 }
2399                 return WERR_OK;
2400         }
2401
2402         if (!StrCaseCmp(value, "DNSMachineName")) {
2403                 const char *hostname = get_mydnsfullname();
2404
2405                 if (!hostname) {
2406                         return WERR_BADFILE;
2407                 }
2408
2409                 *type = REG_SZ;
2410                 data->string = talloc_strdup(mem_ctx, hostname);
2411                 W_ERROR_HAVE_NO_MEMORY(data->string);
2412
2413                 return WERR_OK;
2414         }
2415
2416         *type = REG_NONE;
2417
2418         return WERR_INVALID_PARAM;
2419 }
2420
2421 /****************************************************************
2422  _spoolss_GetPrinterData
2423 ****************************************************************/
2424
2425 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2426                                struct spoolss_GetPrinterData *r)
2427 {
2428         struct spoolss_GetPrinterDataEx r2;
2429
2430         r2.in.handle            = r->in.handle;
2431         r2.in.key_name          = "PrinterDriverData";
2432         r2.in.value_name        = r->in.value_name;
2433         r2.in.offered           = r->in.offered;
2434         r2.out.type             = r->out.type;
2435         r2.out.data             = r->out.data;
2436         r2.out.needed           = r->out.needed;
2437
2438         return _spoolss_GetPrinterDataEx(p, &r2);
2439 }
2440
2441 /*********************************************************
2442  Connect to the client machine.
2443 **********************************************************/
2444
2445 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2446                         struct sockaddr_storage *client_ss, const char *remote_machine)
2447 {
2448         NTSTATUS ret;
2449         struct cli_state *the_cli;
2450         struct sockaddr_storage rm_addr;
2451         char addr[INET6_ADDRSTRLEN];
2452
2453         if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2454                 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2455                         remote_machine));
2456                 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2457                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2458                         return false;
2459                 }
2460                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2461         } else {
2462                 rm_addr = *client_ss;
2463                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2464                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2465                         addr));
2466         }
2467
2468         if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2469                 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2470                         addr));
2471                 return false;
2472         }
2473
2474         /* setup the connection */
2475         ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2476                 &rm_addr, 0, "IPC$", "IPC",
2477                 "", /* username */
2478                 "", /* domain */
2479                 "", /* password */
2480                 0, lp_client_signing(), NULL );
2481
2482         if ( !NT_STATUS_IS_OK( ret ) ) {
2483                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2484                         remote_machine ));
2485                 return false;
2486         }
2487
2488         if ( the_cli->protocol != PROTOCOL_NT1 ) {
2489                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2490                 cli_shutdown(the_cli);
2491                 return false;
2492         }
2493
2494         /*
2495          * Ok - we have an anonymous connection to the IPC$ share.
2496          * Now start the NT Domain stuff :-).
2497          */
2498
2499         ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2500         if (!NT_STATUS_IS_OK(ret)) {
2501                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2502                         remote_machine, nt_errstr(ret)));
2503                 cli_shutdown(the_cli);
2504                 return false;
2505         }
2506
2507         return true;
2508 }
2509
2510 /***************************************************************************
2511  Connect to the client.
2512 ****************************************************************************/
2513
2514 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2515                                         uint32_t localprinter,
2516                                         enum winreg_Type type,
2517                                         struct policy_handle *handle,
2518                                         struct notify_back_channel **_chan,
2519                                         struct sockaddr_storage *client_ss,
2520                                         struct messaging_context *msg_ctx)
2521 {
2522         WERROR result;
2523         NTSTATUS status;
2524         struct notify_back_channel *chan;
2525
2526         for (chan = back_channels; chan; chan = chan->next) {
2527                 if (memcmp(&chan->client_address, client_ss,
2528                            sizeof(struct sockaddr_storage)) == 0) {
2529                         break;
2530                 }
2531         }
2532
2533         /*
2534          * If it's the first connection, contact the client
2535          * and connect to the IPC$ share anonymously
2536          */
2537         if (!chan) {
2538                 fstring unix_printer;
2539
2540                 /* the +2 is to strip the leading 2 backslashs */
2541                 fstrcpy(unix_printer, printer + 2);
2542
2543                 chan = talloc_zero(back_channels, struct notify_back_channel);
2544                 if (!chan) {
2545                         return false;
2546                 }
2547                 chan->client_address = *client_ss;
2548
2549                 if (!spoolss_connect_to_client(&chan->cli_pipe, client_ss, unix_printer)) {
2550                         TALLOC_FREE(chan);
2551                         return false;
2552                 }
2553
2554                 DLIST_ADD(back_channels, chan);
2555
2556                 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2557                                    receive_notify2_message_list);
2558                 /* Tell the connections db we're now interested in printer
2559                  * notify messages. */
2560                 serverid_register_msg_flags(messaging_server_id(msg_ctx),
2561                                             true, FLAG_MSG_PRINT_NOTIFY);
2562         }
2563
2564         /*
2565          * Tell the specific printing tdb we want messages for this printer
2566          * by registering our PID.
2567          */
2568
2569         if (!print_notify_register_pid(snum)) {
2570                 DEBUG(0, ("Failed to register our pid for printer %s\n",
2571                           printer));
2572         }
2573
2574         status = rpccli_spoolss_ReplyOpenPrinter(chan->cli_pipe, talloc_tos(),
2575                                                  printer,
2576                                                  localprinter,
2577                                                  type,
2578                                                  0,
2579                                                  NULL,
2580                                                  handle,
2581                                                  &result);
2582         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result)) {
2583                 DEBUG(5, ("Client RPC returned [%s]\n", win_errstr(result)));
2584         }
2585
2586         chan->active_connections++;
2587         *_chan = chan;
2588
2589         return (W_ERROR_IS_OK(result));
2590 }
2591
2592 /****************************************************************
2593  ****************************************************************/
2594
2595 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2596                                                              const struct spoolss_NotifyOption *r)
2597 {
2598         struct spoolss_NotifyOption *option;
2599         uint32_t i,k;
2600
2601         if (!r) {
2602                 return NULL;
2603         }
2604
2605         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2606         if (!option) {
2607                 return NULL;
2608         }
2609
2610         *option = *r;
2611
2612         if (!option->count) {
2613                 return option;
2614         }
2615
2616         option->types = talloc_zero_array(option,
2617                 struct spoolss_NotifyOptionType, option->count);
2618         if (!option->types) {
2619                 talloc_free(option);
2620                 return NULL;
2621         }
2622
2623         for (i=0; i < option->count; i++) {
2624                 option->types[i] = r->types[i];
2625
2626                 if (option->types[i].count) {
2627                         option->types[i].fields = talloc_zero_array(option,
2628                                 union spoolss_Field, option->types[i].count);
2629                         if (!option->types[i].fields) {
2630                                 talloc_free(option);
2631                                 return NULL;
2632                         }
2633                         for (k=0; k<option->types[i].count; k++) {
2634                                 option->types[i].fields[k] =
2635                                         r->types[i].fields[k];
2636                         }
2637                 }
2638         }
2639
2640         return option;
2641 }
2642
2643 /****************************************************************
2644  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2645  *
2646  * before replying OK: status=0 a rpc call is made to the workstation
2647  * asking ReplyOpenPrinter
2648  *
2649  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2650  * called from api_spoolss_rffpcnex
2651 ****************************************************************/
2652
2653 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2654                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2655 {
2656         int snum = -1;
2657         struct spoolss_NotifyOption *option = r->in.notify_options;
2658         struct sockaddr_storage client_ss;
2659
2660         /* store the notify value in the printer struct */
2661
2662         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2663
2664         if (!Printer) {
2665                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2666                         "Invalid handle (%s:%u:%u).\n",
2667                         OUR_HANDLE(r->in.handle)));
2668                 return WERR_BADFID;
2669         }
2670
2671         Printer->notify.flags           = r->in.flags;
2672         Printer->notify.options         = r->in.options;
2673         Printer->notify.printerlocal    = r->in.printer_local;
2674         Printer->notify.msg_ctx         = p->msg_ctx;
2675
2676         TALLOC_FREE(Printer->notify.option);
2677         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2678
2679         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2680
2681         /* Connect to the client machine and send a ReplyOpenPrinter */
2682
2683         if ( Printer->printer_type == SPLHND_SERVER)
2684                 snum = -1;
2685         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2686                         !get_printer_snum(p, r->in.handle, &snum, NULL) )
2687                 return WERR_BADFID;
2688
2689         DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2690                 "client_address is %s\n", p->client_id->addr));
2691
2692         if (!interpret_string_addr(&client_ss, p->client_id->addr,
2693                                    AI_NUMERICHOST)) {
2694                 return WERR_SERVER_UNAVAILABLE;
2695         }
2696
2697         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2698                                         Printer->notify.printerlocal, REG_SZ,
2699                                         &Printer->notify.cli_hnd,
2700                                         &Printer->notify.cli_chan,
2701                                         &client_ss, p->msg_ctx)) {
2702                 return WERR_SERVER_UNAVAILABLE;
2703         }
2704
2705         return WERR_OK;
2706 }
2707
2708 /*******************************************************************
2709  * fill a notify_info_data with the servername
2710  ********************************************************************/
2711
2712 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2713                                        int snum,
2714                                        struct spoolss_Notify *data,
2715                                        print_queue_struct *queue,
2716                                        struct spoolss_PrinterInfo2 *pinfo2,
2717                                        TALLOC_CTX *mem_ctx)
2718 {
2719         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2720 }
2721
2722 /*******************************************************************
2723  * fill a notify_info_data with the printername (not including the servername).
2724  ********************************************************************/
2725
2726 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2727                                         int snum,
2728                                         struct spoolss_Notify *data,
2729                                         print_queue_struct *queue,
2730                                         struct spoolss_PrinterInfo2 *pinfo2,
2731                                         TALLOC_CTX *mem_ctx)
2732 {
2733         /* the notify name should not contain the \\server\ part */
2734         const char *p = strrchr(pinfo2->printername, '\\');
2735
2736         if (!p) {
2737                 p = pinfo2->printername;
2738         } else {
2739                 p++;
2740         }
2741
2742         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2743 }
2744
2745 /*******************************************************************
2746  * fill a notify_info_data with the servicename
2747  ********************************************************************/
2748
2749 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2750                                       int snum,
2751                                       struct spoolss_Notify *data,
2752                                       print_queue_struct *queue,
2753                                       struct spoolss_PrinterInfo2 *pinfo2,
2754                                       TALLOC_CTX *mem_ctx)
2755 {
2756         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2757 }
2758
2759 /*******************************************************************
2760  * fill a notify_info_data with the port name
2761  ********************************************************************/
2762
2763 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2764                                      int snum,
2765                                      struct spoolss_Notify *data,
2766                                      print_queue_struct *queue,
2767                                      struct spoolss_PrinterInfo2 *pinfo2,
2768                                      TALLOC_CTX *mem_ctx)
2769 {
2770         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2771 }
2772
2773 /*******************************************************************
2774  * fill a notify_info_data with the printername
2775  * but it doesn't exist, have to see what to do
2776  ********************************************************************/
2777
2778 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2779                                        int snum,
2780                                        struct spoolss_Notify *data,
2781                                        print_queue_struct *queue,
2782                                        struct spoolss_PrinterInfo2 *pinfo2,
2783                                        TALLOC_CTX *mem_ctx)
2784 {
2785         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2786 }
2787
2788 /*******************************************************************
2789  * fill a notify_info_data with the comment
2790  ********************************************************************/
2791
2792 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2793                                    int snum,
2794                                    struct spoolss_Notify *data,
2795                                    print_queue_struct *queue,
2796                                    struct spoolss_PrinterInfo2 *pinfo2,
2797                                    TALLOC_CTX *mem_ctx)
2798 {
2799         const char *p;
2800
2801         if (*pinfo2->comment == '\0') {
2802                 p = lp_comment(snum);
2803         } else {
2804                 p = pinfo2->comment;
2805         }
2806
2807         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2808 }
2809
2810 /*******************************************************************
2811  * fill a notify_info_data with the comment
2812  * location = "Room 1, floor 2, building 3"
2813  ********************************************************************/
2814
2815 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2816                                     int snum,
2817                                     struct spoolss_Notify *data,
2818                                     print_queue_struct *queue,
2819                                     struct spoolss_PrinterInfo2 *pinfo2,
2820                                     TALLOC_CTX *mem_ctx)
2821 {
2822         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->location);
2823 }
2824
2825 /*******************************************************************
2826  * fill a notify_info_data with the device mode
2827  * jfm:xxxx don't to it for know but that's a real problem !!!
2828  ********************************************************************/
2829
2830 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2831                                    int snum,
2832                                    struct spoolss_Notify *data,
2833                                    print_queue_struct *queue,
2834                                    struct spoolss_PrinterInfo2 *pinfo2,
2835                                    TALLOC_CTX *mem_ctx)
2836 {
2837         /* for a dummy implementation we have to zero the fields */
2838         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2839 }
2840
2841 /*******************************************************************
2842  * fill a notify_info_data with the separator file name
2843  ********************************************************************/
2844
2845 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2846                                    int snum,
2847                                    struct spoolss_Notify *data,
2848                                    print_queue_struct *queue,
2849                                    struct spoolss_PrinterInfo2 *pinfo2,
2850                                    TALLOC_CTX *mem_ctx)
2851 {
2852         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2853 }
2854
2855 /*******************************************************************
2856  * fill a notify_info_data with the print processor
2857  * jfm:xxxx return always winprint to indicate we don't do anything to it
2858  ********************************************************************/
2859
2860 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2861                                            int snum,
2862                                            struct spoolss_Notify *data,
2863                                            print_queue_struct *queue,
2864                                            struct spoolss_PrinterInfo2 *pinfo2,
2865                                            TALLOC_CTX *mem_ctx)
2866 {
2867         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2868 }
2869
2870 /*******************************************************************
2871  * fill a notify_info_data with the print processor options
2872  * jfm:xxxx send an empty string
2873  ********************************************************************/
2874
2875 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2876                                       int snum,
2877                                       struct spoolss_Notify *data,
2878                                       print_queue_struct *queue,
2879                                       struct spoolss_PrinterInfo2 *pinfo2,
2880                                       TALLOC_CTX *mem_ctx)
2881 {
2882         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2883 }
2884
2885 /*******************************************************************
2886  * fill a notify_info_data with the data type
2887  * jfm:xxxx always send RAW as data type
2888  ********************************************************************/
2889
2890 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2891                                     int snum,
2892                                     struct spoolss_Notify *data,
2893                                     print_queue_struct *queue,
2894                                     struct spoolss_PrinterInfo2 *pinfo2,
2895                                     TALLOC_CTX *mem_ctx)
2896 {
2897         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2898 }
2899
2900 /*******************************************************************
2901  * fill a notify_info_data with the security descriptor
2902  * jfm:xxxx send an null pointer to say no security desc
2903  * have to implement security before !
2904  ********************************************************************/
2905
2906 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2907                                          int snum,
2908                                          struct spoolss_Notify *data,
2909                                          print_queue_struct *queue,
2910                                          struct spoolss_PrinterInfo2 *pinfo2,
2911                                          TALLOC_CTX *mem_ctx)
2912 {
2913         SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
2914 }
2915
2916 /*******************************************************************
2917  * fill a notify_info_data with the attributes
2918  * jfm:xxxx a samba printer is always shared
2919  ********************************************************************/
2920
2921 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2922                                       int snum,
2923                                       struct spoolss_Notify *data,
2924                                       print_queue_struct *queue,
2925                                       struct spoolss_PrinterInfo2 *pinfo2,
2926                                       TALLOC_CTX *mem_ctx)
2927 {
2928         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2929 }
2930
2931 /*******************************************************************
2932  * fill a notify_info_data with the priority
2933  ********************************************************************/
2934
2935 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
2936                                     int snum,
2937                                     struct spoolss_Notify *data,
2938                                     print_queue_struct *queue,
2939                                     struct spoolss_PrinterInfo2 *pinfo2,
2940                                     TALLOC_CTX *mem_ctx)
2941 {
2942         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
2943 }
2944
2945 /*******************************************************************
2946  * fill a notify_info_data with the default priority
2947  ********************************************************************/
2948
2949 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
2950                                             int snum,
2951                                             struct spoolss_Notify *data,
2952                                             print_queue_struct *queue,
2953                                             struct spoolss_PrinterInfo2 *pinfo2,
2954                                             TALLOC_CTX *mem_ctx)
2955 {
2956         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
2957 }
2958
2959 /*******************************************************************
2960  * fill a notify_info_data with the start time
2961  ********************************************************************/
2962
2963 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
2964                                       int snum,
2965                                       struct spoolss_Notify *data,
2966                                       print_queue_struct *queue,
2967                                       struct spoolss_PrinterInfo2 *pinfo2,
2968                                       TALLOC_CTX *mem_ctx)
2969 {
2970         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
2971 }
2972
2973 /*******************************************************************
2974  * fill a notify_info_data with the until time
2975  ********************************************************************/
2976
2977 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
2978                                       int snum,
2979                                       struct spoolss_Notify *data,
2980                                       print_queue_struct *queue,
2981                                       struct spoolss_PrinterInfo2 *pinfo2,
2982                                       TALLOC_CTX *mem_ctx)
2983 {
2984         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
2985 }
2986
2987 /*******************************************************************
2988  * fill a notify_info_data with the status
2989  ********************************************************************/
2990
2991 static void spoolss_notify_status(struct messaging_context *msg_ctx,
2992                                   int snum,
2993                                   struct spoolss_Notify *data,
2994                                   print_queue_struct *queue,
2995                                   struct spoolss_PrinterInfo2 *pinfo2,
2996                                   TALLOC_CTX *mem_ctx)
2997 {
2998         print_status_struct status;
2999
3000         print_queue_length(msg_ctx, snum, &status);
3001         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3002 }
3003
3004 /*******************************************************************
3005  * fill a notify_info_data with the number of jobs queued
3006  ********************************************************************/
3007
3008 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3009                                  int snum,
3010                                  struct spoolss_Notify *data,
3011                                  print_queue_struct *queue,
3012                                  struct spoolss_PrinterInfo2 *pinfo2,
3013                                  TALLOC_CTX *mem_ctx)
3014 {
3015         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3016                 data, print_queue_length(msg_ctx, snum, NULL));
3017 }
3018
3019 /*******************************************************************
3020  * fill a notify_info_data with the average ppm
3021  ********************************************************************/
3022
3023 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3024                                        int snum,
3025                                        struct spoolss_Notify *data,
3026                                        print_queue_struct *queue,
3027                                        struct spoolss_PrinterInfo2 *pinfo2,
3028                                        TALLOC_CTX *mem_ctx)
3029 {
3030         /* always respond 8 pages per minutes */
3031         /* a little hard ! */
3032         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3033 }
3034
3035 /*******************************************************************
3036  * fill a notify_info_data with username
3037  ********************************************************************/
3038
3039 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3040                                     int snum,
3041                                     struct spoolss_Notify *data,
3042                                     print_queue_struct *queue,
3043                                     struct spoolss_PrinterInfo2 *pinfo2,
3044                                     TALLOC_CTX *mem_ctx)
3045 {
3046         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3047 }
3048
3049 /*******************************************************************
3050  * fill a notify_info_data with job status
3051  ********************************************************************/
3052
3053 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3054                                       int snum,
3055                                       struct spoolss_Notify *data,
3056                                       print_queue_struct *queue,
3057                                       struct spoolss_PrinterInfo2 *pinfo2,
3058                                       TALLOC_CTX *mem_ctx)
3059 {
3060         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3061 }
3062
3063 /*******************************************************************
3064  * fill a notify_info_data with job name
3065  ********************************************************************/
3066
3067 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3068                                     int snum,
3069                                     struct spoolss_Notify *data,
3070                                     print_queue_struct *queue,
3071                                     struct spoolss_PrinterInfo2 *pinfo2,
3072                                     TALLOC_CTX *mem_ctx)
3073 {
3074         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3075 }
3076
3077 /*******************************************************************
3078  * fill a notify_info_data with job status
3079  ********************************************************************/
3080
3081 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3082                                              int snum,
3083                                              struct spoolss_Notify *data,
3084                                              print_queue_struct *queue,
3085                                              struct spoolss_PrinterInfo2 *pinfo2,
3086                                              TALLOC_CTX *mem_ctx)
3087 {
3088         /*
3089          * Now we're returning job status codes we just return a "" here. JRA.
3090          */
3091
3092         const char *p = "";
3093
3094 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3095         p = "unknown";
3096
3097         switch (queue->status) {
3098         case LPQ_QUEUED:
3099                 p = "Queued";
3100                 break;
3101         case LPQ_PAUSED:
3102                 p = "";    /* NT provides the paused string */
3103                 break;
3104         case LPQ_SPOOLING:
3105                 p = "Spooling";
3106                 break;
3107         case LPQ_PRINTING:
3108                 p = "Printing";
3109                 break;
3110         }
3111 #endif /* NO LONGER NEEDED. */
3112
3113         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3114 }
3115
3116 /*******************************************************************
3117  * fill a notify_info_data with job time
3118  ********************************************************************/
3119
3120 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3121                                     int snum,
3122                                     struct spoolss_Notify *data,
3123                                     print_queue_struct *queue,
3124                                     struct spoolss_PrinterInfo2 *pinfo2,
3125                                     TALLOC_CTX *mem_ctx)
3126 {
3127         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3128 }
3129
3130 /*******************************************************************
3131  * fill a notify_info_data with job size
3132  ********************************************************************/
3133
3134 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3135                                     int snum,
3136                                     struct spoolss_Notify *data,
3137                                     print_queue_struct *queue,
3138                                     struct spoolss_PrinterInfo2 *pinfo2,
3139                                     TALLOC_CTX *mem_ctx)
3140 {
3141         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3142 }
3143
3144 /*******************************************************************
3145  * fill a notify_info_data with page info
3146  ********************************************************************/
3147 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3148                                        int snum,
3149                                 struct spoolss_Notify *data,
3150                                 print_queue_struct *queue,
3151                                 struct spoolss_PrinterInfo2 *pinfo2,
3152                                 TALLOC_CTX *mem_ctx)
3153 {
3154         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3155 }
3156
3157 /*******************************************************************
3158  * fill a notify_info_data with pages printed info.
3159  ********************************************************************/
3160 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3161                                          int snum,
3162                                 struct spoolss_Notify *data,
3163                                 print_queue_struct *queue,
3164                                 struct spoolss_PrinterInfo2 *pinfo2,
3165                                 TALLOC_CTX *mem_ctx)
3166 {
3167         /* Add code when back-end tracks this */
3168         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3169 }
3170
3171 /*******************************************************************
3172  Fill a notify_info_data with job position.
3173  ********************************************************************/
3174
3175 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3176                                         int snum,
3177                                         struct spoolss_Notify *data,
3178                                         print_queue_struct *queue,
3179                                         struct spoolss_PrinterInfo2 *pinfo2,
3180                                         TALLOC_CTX *mem_ctx)
3181 {
3182         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3183 }
3184
3185 /*******************************************************************
3186  Fill a notify_info_data with submitted time.
3187  ********************************************************************/
3188
3189 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3190                                           int snum,
3191                                           struct spoolss_Notify *data,
3192                                           print_queue_struct *queue,
3193                                           struct spoolss_PrinterInfo2 *pinfo2,
3194                                           TALLOC_CTX *mem_ctx)
3195 {
3196         data->data.string.string = NULL;
3197         data->data.string.size = 0;
3198
3199         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3200                                &data->data.string.string,
3201                                &data->data.string.size);
3202
3203 }
3204
3205 struct s_notify_info_data_table
3206 {
3207         enum spoolss_NotifyType type;
3208         uint16_t field;
3209         const char *name;
3210         enum spoolss_NotifyTable variable_type;
3211         void (*fn) (struct messaging_context *msg_ctx,
3212                     int snum, struct spoolss_Notify *data,
3213                     print_queue_struct *queue,
3214                     struct spoolss_PrinterInfo2 *pinfo2,
3215                     TALLOC_CTX *mem_ctx);
3216 };
3217
3218 /* A table describing the various print notification constants and
3219    whether the notification data is a pointer to a variable sized
3220    buffer, a one value uint32_t or a two value uint32_t. */
3221
3222 static const struct s_notify_info_data_table notify_info_data_table[] =
3223 {
3224 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME,         "PRINTER_NOTIFY_FIELD_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3225 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME,        "PRINTER_NOTIFY_FIELD_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3226 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME,          "PRINTER_NOTIFY_FIELD_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
3227 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME,           "PRINTER_NOTIFY_FIELD_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3228 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME,         "PRINTER_NOTIFY_FIELD_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3229 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT,             "PRINTER_NOTIFY_FIELD_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
3230 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION,            "PRINTER_NOTIFY_FIELD_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
3231 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE,             "PRINTER_NOTIFY_FIELD_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3232 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE,             "PRINTER_NOTIFY_FIELD_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
3233 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR,     "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3234 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS,          "PRINTER_NOTIFY_FIELD_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3235 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE,            "PRINTER_NOTIFY_FIELD_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3236 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
3237 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES,          "PRINTER_NOTIFY_FIELD_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
3238 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY,            "PRINTER_NOTIFY_FIELD_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3239 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
3240 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME,          "PRINTER_NOTIFY_FIELD_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3241 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME,          "PRINTER_NOTIFY_FIELD_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3242 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS,              "PRINTER_NOTIFY_FIELD_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
3243 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING,       "PRINTER_NOTIFY_FIELD_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
3244 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS,               "PRINTER_NOTIFY_FIELD_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
3245 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM,         "PRINTER_NOTIFY_FIELD_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
3246 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES,         "PRINTER_NOTIFY_FIELD_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
3247 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED,       "PRINTER_NOTIFY_FIELD_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3248 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES,         "PRINTER_NOTIFY_FIELD_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
3249 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED,       "PRINTER_NOTIFY_FIELD_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3250 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINTER_NAME,            "JOB_NOTIFY_FIELD_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3251 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_MACHINE_NAME,            "JOB_NOTIFY_FIELD_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3252 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PORT_NAME,               "JOB_NOTIFY_FIELD_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3253 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_USER_NAME,               "JOB_NOTIFY_FIELD_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
3254 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_NOTIFY_NAME,             "JOB_NOTIFY_FIELD_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
3255 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DATATYPE,                "JOB_NOTIFY_FIELD_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3256 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINT_PROCESSOR,         "JOB_NOTIFY_FIELD_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3257 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PARAMETERS,              "JOB_NOTIFY_FIELD_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3258 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DRIVER_NAME,             "JOB_NOTIFY_FIELD_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3259 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DEVMODE,                 "JOB_NOTIFY_FIELD_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3260 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS,                  "JOB_NOTIFY_FIELD_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
3261 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS_STRING,           "JOB_NOTIFY_FIELD_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
3262 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
3263 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DOCUMENT,                "JOB_NOTIFY_FIELD_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
3264 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRIORITY,                "JOB_NOTIFY_FIELD_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3265 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_POSITION,                "JOB_NOTIFY_FIELD_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
3266 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SUBMITTED,               "JOB_NOTIFY_FIELD_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
3267 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_START_TIME,              "JOB_NOTIFY_FIELD_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3268 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_UNTIL_TIME,              "JOB_NOTIFY_FIELD_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3269 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TIME,                    "JOB_NOTIFY_FIELD_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
3270 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_PAGES,             "JOB_NOTIFY_FIELD_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
3271 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PAGES_PRINTED,           "JOB_NOTIFY_FIELD_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
3272 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_BYTES,             "JOB_NOTIFY_FIELD_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
3273 };
3274
3275 /*******************************************************************
3276  Return the variable_type of info_data structure.
3277 ********************************************************************/
3278
3279 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3280                                                                   uint16_t field)
3281 {
3282         int i=0;
3283
3284         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3285                 if ( (notify_info_data_table[i].type == type) &&
3286                      (notify_info_data_table[i].field == field) ) {
3287                         return notify_info_data_table[i].variable_type;
3288                 }
3289         }
3290
3291         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3292
3293         return (enum spoolss_NotifyTable) 0;
3294 }
3295
3296 /****************************************************************************
3297 ****************************************************************************/
3298
3299 static bool search_notify(enum spoolss_NotifyType type,
3300                           uint16_t field,
3301                           int *value)
3302 {
3303         int i;
3304
3305         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3306                 if (notify_info_data_table[i].type == type &&
3307                     notify_info_data_table[i].field == field &&
3308                     notify_info_data_table[i].fn != NULL) {
3309                         *value = i;
3310                         return true;
3311                 }
3312         }
3313
3314         return false;
3315 }
3316
3317 /****************************************************************************
3318 ****************************************************************************/
3319
3320 static void construct_info_data(struct spoolss_Notify *info_data,
3321                                 enum spoolss_NotifyType type,
3322                                 uint16_t field, int id)
3323 {
3324         info_data->type                 = type;
3325         info_data->field.field          = field;
3326         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3327         info_data->job_id               = id;
3328 }
3329
3330 /*******************************************************************
3331  *
3332  * fill a notify_info struct with info asked
3333  *
3334  ********************************************************************/
3335
3336 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3337                                           struct printer_handle *print_hnd,
3338                                           struct spoolss_NotifyInfo *info,
3339                                           struct spoolss_PrinterInfo2 *pinfo2,
3340                                           int snum,
3341                                           const struct spoolss_NotifyOptionType *option_type,
3342                                           uint32_t id,
3343                                           TALLOC_CTX *mem_ctx)
3344 {
3345         int field_num,j;
3346         enum spoolss_NotifyType type;
3347         uint16_t field;
3348
3349         struct spoolss_Notify *current_data;
3350         print_queue_struct *queue=NULL;
3351
3352         type = option_type->type;
3353
3354         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3355                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3356                 option_type->count, lp_servicename(snum)));
3357
3358         for(field_num=0; field_num < option_type->count; field_num++) {
3359                 field = option_type->fields[field_num].field;
3360
3361                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3362
3363                 if (!search_notify(type, field, &j) )
3364                         continue;
3365
3366                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3367                                                       struct spoolss_Notify,
3368                                                       info->count + 1);
3369                 if (info->notifies == NULL) {
3370                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3371                         return false;
3372                 }
3373
3374                 current_data = &info->notifies[info->count];
3375
3376                 construct_info_data(current_data, type, field, id);
3377
3378                 DEBUG(10, ("construct_notify_printer_info: "
3379                            "calling [%s]  snum=%d  printername=[%s])\n",
3380                            notify_info_data_table[j].name, snum,
3381                            pinfo2->printername));
3382
3383                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3384                                              queue, pinfo2, mem_ctx);
3385
3386                 info->count++;
3387         }
3388
3389         return true;
3390 }
3391
3392 /*******************************************************************
3393  *
3394  * fill a notify_info struct with info asked
3395  *
3396  ********************************************************************/
3397
3398 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3399                                        print_queue_struct *queue,
3400                                        struct spoolss_NotifyInfo *info,
3401                                        struct spoolss_PrinterInfo2 *pinfo2,
3402                                        int snum,
3403                                        const struct spoolss_NotifyOptionType *option_type,
3404                                        uint32_t id,
3405                                        TALLOC_CTX *mem_ctx)
3406 {
3407         int field_num,j;
3408         enum spoolss_NotifyType type;
3409         uint16_t field;
3410         struct spoolss_Notify *current_data;
3411
3412         DEBUG(4,("construct_notify_jobs_info\n"));
3413
3414         type = option_type->type;
3415
3416         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3417                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3418                 option_type->count));
3419
3420         for(field_num=0; field_num<option_type->count; field_num++) {
3421                 field = option_type->fields[field_num].field;
3422
3423                 if (!search_notify(type, field, &j) )
3424                         continue;
3425
3426                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3427                                                       struct spoolss_Notify,
3428                                                       info->count + 1);
3429                 if (info->notifies == NULL) {
3430                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3431                         return false;
3432                 }
3433
3434                 current_data=&(info->notifies[info->count]);
3435
3436                 construct_info_data(current_data, type, field, id);
3437                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3438                                              queue, pinfo2, mem_ctx);
3439                 info->count++;
3440         }
3441
3442         return true;
3443 }
3444
3445 /*
3446  * JFM: The enumeration is not that simple, it's even non obvious.
3447  *
3448  * let's take an example: I want to monitor the PRINTER SERVER for
3449  * the printer's name and the number of jobs currently queued.
3450  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3451  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3452  *
3453  * I have 3 printers on the back of my server.
3454  *
3455  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3456  * structures.
3457  *   Number     Data                    Id
3458  *      1       printer 1 name          1
3459  *      2       printer 1 cjob          1
3460  *      3       printer 2 name          2
3461  *      4       printer 2 cjob          2
3462  *      5       printer 3 name          3
3463  *      6       printer 3 name          3
3464  *
3465  * that's the print server case, the printer case is even worse.
3466  */
3467
3468 /*******************************************************************
3469  *
3470  * enumerate all printers on the printserver
3471  * fill a notify_info struct with info asked
3472  *
3473  ********************************************************************/
3474
3475 static WERROR printserver_notify_info(struct pipes_struct *p,
3476                                       struct policy_handle *hnd,
3477                                       struct spoolss_NotifyInfo *info,
3478                                       TALLOC_CTX *mem_ctx)
3479 {
3480         int snum;
3481         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3482         int n_services=lp_numservices();
3483         int i;
3484         struct spoolss_NotifyOption *option;
3485         struct spoolss_NotifyOptionType option_type;
3486         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3487         WERROR result;
3488
3489         DEBUG(4,("printserver_notify_info\n"));
3490
3491         if (!Printer)
3492                 return WERR_BADFID;
3493
3494         option = Printer->notify.option;
3495
3496         info->version   = 2;
3497         info->notifies  = NULL;
3498         info->count     = 0;
3499
3500         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3501            sending a ffpcn() request first */
3502
3503         if ( !option )
3504                 return WERR_BADFID;
3505
3506         for (i=0; i<option->count; i++) {
3507                 option_type = option->types[i];
3508
3509                 if (option_type.type != PRINTER_NOTIFY_TYPE)
3510                         continue;
3511
3512                 for (snum = 0; snum < n_services; snum++) {
3513                         if (!lp_browseable(snum) ||
3514                             !lp_snum_ok(snum) ||
3515                             !lp_print_ok(snum)) {
3516                                 continue; /* skip */
3517                         }
3518
3519                         /* Maybe we should use the SYSTEM server_info here... */
3520                         result = winreg_get_printer(mem_ctx,
3521                                                     get_server_info_system(),
3522                                                     p->msg_ctx,
3523                                                     lp_servicename(snum),
3524                                                     &pinfo2);
3525                         if (!W_ERROR_IS_OK(result)) {
3526                                 DEBUG(4, ("printserver_notify_info: "
3527                                           "Failed to get printer [%s]\n",
3528                                           lp_servicename(snum)));
3529                                 continue;
3530                         }
3531
3532
3533                         construct_notify_printer_info(p->msg_ctx,
3534                                                       Printer, info,
3535                                                       pinfo2, snum,
3536                                                       &option_type, snum,
3537                                                       mem_ctx);
3538
3539                         TALLOC_FREE(pinfo2);
3540                 }
3541         }
3542
3543 #if 0
3544         /*
3545          * Debugging information, don't delete.
3546          */
3547
3548         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3549         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3550         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3551
3552         for (i=0; i<info->count; i++) {
3553                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3554                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3555                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3556         }
3557 #endif
3558
3559         return WERR_OK;
3560 }
3561
3562 /*******************************************************************
3563  *
3564  * fill a notify_info struct with info asked
3565  *
3566  ********************************************************************/
3567
3568 static WERROR printer_notify_info(struct pipes_struct *p,
3569                                   struct policy_handle *hnd,
3570                                   struct spoolss_NotifyInfo *info,
3571                                   TALLOC_CTX *mem_ctx)
3572 {
3573         int snum;
3574         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3575         int i;
3576         uint32_t id;
3577         struct spoolss_NotifyOption *option;
3578         struct spoolss_NotifyOptionType option_type;
3579         int count,j;
3580         print_queue_struct *queue=NULL;
3581         print_status_struct status;
3582         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3583         WERROR result;
3584
3585         DEBUG(4,("printer_notify_info\n"));
3586
3587         if (!Printer)
3588                 return WERR_BADFID;
3589
3590         option = Printer->notify.option;
3591         id = 0x0;
3592
3593         info->version   = 2;
3594         info->notifies  = NULL;
3595         info->count     = 0;
3596
3597         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3598            sending a ffpcn() request first */
3599
3600         if ( !option )
3601                 return WERR_BADFID;
3602
3603         get_printer_snum(p, hnd, &snum, NULL);
3604
3605         /* Maybe we should use the SYSTEM server_info here... */
3606         result = winreg_get_printer(mem_ctx,
3607                                     get_server_info_system(),
3608                                     p->msg_ctx,
3609                                     lp_servicename(snum), &pinfo2);
3610         if (!W_ERROR_IS_OK(result)) {
3611                 return WERR_BADFID;
3612         }
3613
3614         for (i=0; i<option->count; i++) {
3615                 option_type = option->types[i];
3616
3617                 switch (option_type.type) {
3618                 case PRINTER_NOTIFY_TYPE:
3619                         if (construct_notify_printer_info(p->msg_ctx,
3620                                                           Printer, info,
3621                                                           pinfo2, snum,
3622                                                           &option_type, id,
3623                                                           mem_ctx)) {
3624                                 id--;
3625                         }
3626                         break;
3627
3628                 case JOB_NOTIFY_TYPE:
3629
3630                         count = print_queue_status(p->msg_ctx, snum, &queue,
3631                                                    &status);
3632
3633                         for (j=0; j<count; j++) {
3634                                 construct_notify_jobs_info(p->msg_ctx,
3635                                                            &queue[j], info,
3636                                                            pinfo2, snum,
3637                                                            &option_type,
3638                                                            queue[j].job,
3639                                                            mem_ctx);
3640                         }
3641
3642                         SAFE_FREE(queue);
3643                         break;
3644                 }
3645         }
3646
3647         /*
3648          * Debugging information, don't delete.
3649          */
3650         /*
3651         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3652         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3653         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3654
3655         for (i=0; i<info->count; i++) {
3656                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3657                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3658                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3659         }
3660         */
3661
3662         talloc_free(pinfo2);
3663         return WERR_OK;
3664 }
3665
3666 /****************************************************************
3667  _spoolss_RouterRefreshPrinterChangeNotify
3668 ****************************************************************/
3669
3670 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3671                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3672 {
3673         struct spoolss_NotifyInfo *info;
3674
3675         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3676         WERROR result = WERR_BADFID;
3677
3678         /* we always have a spoolss_NotifyInfo struct */
3679         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3680         if (!info) {
3681                 result = WERR_NOMEM;
3682                 goto done;
3683         }
3684
3685         *r->out.info = info;
3686
3687         if (!Printer) {
3688                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3689                         "Invalid handle (%s:%u:%u).\n",
3690                         OUR_HANDLE(r->in.handle)));
3691                 goto done;
3692         }
3693
3694         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3695
3696         /*
3697          *      We are now using the change value, and
3698          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3699          *      I don't have a global notification system, I'm sending back all the
3700          *      informations even when _NOTHING_ has changed.
3701          */
3702
3703         /* We need to keep track of the change value to send back in
3704            RRPCN replies otherwise our updates are ignored. */
3705
3706         Printer->notify.fnpcn = true;
3707
3708         if (Printer->notify.cli_chan != NULL &&
3709             Printer->notify.cli_chan->active_connections > 0) {
3710                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3711                         "Saving change value in request [%x]\n",
3712                         r->in.change_low));
3713                 Printer->notify.change = r->in.change_low;
3714         }
3715
3716         /* just ignore the spoolss_NotifyOption */
3717
3718         switch (Printer->printer_type) {
3719                 case SPLHND_SERVER:
3720                         result = printserver_notify_info(p, r->in.handle,
3721                                                          info, p->mem_ctx);
3722                         break;
3723
3724                 case SPLHND_PRINTER:
3725                         result = printer_notify_info(p, r->in.handle,
3726                                                      info, p->mem_ctx);
3727                         break;
3728         }
3729
3730         Printer->notify.fnpcn = false;
3731
3732 done:
3733         return result;
3734 }
3735
3736 /********************************************************************
3737  ********************************************************************/
3738
3739 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3740                                  const char *servername,
3741                                  const char *printername,
3742                                  const char **printername_p)
3743 {
3744         /* FIXME: add lp_force_printername() */
3745
3746         if (servername == NULL) {
3747                 *printername_p = talloc_strdup(mem_ctx, printername);
3748                 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3749                 return WERR_OK;
3750         }
3751
3752         if (servername[0] == '\\' && servername[1] == '\\') {
3753                 servername += 2;
3754         }
3755
3756         *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3757         W_ERROR_HAVE_NO_MEMORY(*printername_p);
3758
3759         return WERR_OK;
3760 }
3761
3762 /********************************************************************
3763  ********************************************************************/
3764
3765 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3766                                           const char *printername)
3767 {
3768         if (dm == NULL) {
3769                 return;
3770         }
3771
3772         dm->devicename = talloc_strndup(dm, printername,
3773                                         MIN(strlen(printername), 31));
3774 }
3775
3776 /********************************************************************
3777  * construct_printer_info_0
3778  * fill a printer_info_0 struct
3779  ********************************************************************/
3780
3781 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3782                                       const struct auth_serversupplied_info *server_info,
3783                                       struct messaging_context *msg_ctx,
3784                                       struct spoolss_PrinterInfo2 *info2,
3785                                       const char *servername,
3786                                       struct spoolss_PrinterInfo0 *r,
3787                                       int snum)
3788 {
3789         int count;
3790         struct printer_session_counter *session_counter;
3791         struct timeval setuptime;
3792         print_status_struct status;
3793         WERROR result;
3794
3795         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3796         if (!W_ERROR_IS_OK(result)) {
3797                 return result;
3798         }
3799
3800         if (servername) {
3801                 r->servername = talloc_strdup(mem_ctx, servername);
3802                 W_ERROR_HAVE_NO_MEMORY(r->servername);
3803         } else {
3804                 r->servername = NULL;
3805         }
3806
3807         count = print_queue_length(msg_ctx, snum, &status);
3808
3809         /* check if we already have a counter for this printer */
3810         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3811                 if (session_counter->snum == snum)
3812                         break;
3813         }
3814
3815         /* it's the first time, add it to the list */
3816         if (session_counter == NULL) {
3817                 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3818                 W_ERROR_HAVE_NO_MEMORY(session_counter);
3819                 session_counter->snum           = snum;
3820                 session_counter->counter        = 0;
3821                 DLIST_ADD(counter_list, session_counter);
3822         }
3823
3824         /* increment it */
3825         session_counter->counter++;
3826
3827         r->cjobs                        = count;
3828         r->total_jobs                   = 0;
3829         r->total_bytes                  = 0;
3830
3831         get_startup_time(&setuptime);
3832         init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3833
3834         /* JFM:
3835          * the global_counter should be stored in a TDB as it's common to all the clients
3836          * and should be zeroed on samba startup
3837          */
3838         r->global_counter               = session_counter->counter;
3839         r->total_pages                  = 0;
3840         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3841         SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3842         SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3843         r->free_build                   = SPOOLSS_RELEASE_BUILD;
3844         r->spooling                     = 0;
3845         r->max_spooling                 = 0;
3846         r->session_counter              = session_counter->counter;
3847         r->num_error_out_of_paper       = 0x0;
3848         r->num_error_not_ready          = 0x0;          /* number of print failure */
3849         r->job_error                    = 0x0;
3850         r->number_of_processors         = 0x1;
3851         r->processor_type               = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3852         r->high_part_total_bytes        = 0x0;
3853
3854         /* ChangeID in milliseconds*/
3855         winreg_printer_get_changeid(mem_ctx, server_info, msg_ctx,
3856                                     info2->sharename, &r->change_id);
3857
3858         r->last_error                   = WERR_OK;
3859         r->status                       = nt_printq_status(status.status);
3860         r->enumerate_network_printers   = 0x0;
3861         r->c_setprinter                 = 0x0;
3862         r->processor_architecture       = PROCESSOR_ARCHITECTURE_INTEL;
3863         r->processor_level              = 0x6;          /* 6  ???*/
3864         r->ref_ic                       = 0;
3865         r->reserved2                    = 0;
3866         r->reserved3                    = 0;
3867
3868         return WERR_OK;
3869 }
3870
3871
3872 /********************************************************************
3873  * construct_printer_info1
3874  * fill a spoolss_PrinterInfo1 struct
3875 ********************************************************************/
3876
3877 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3878                                       const struct spoolss_PrinterInfo2 *info2,
3879                                       uint32_t flags,
3880                                       const char *servername,
3881                                       struct spoolss_PrinterInfo1 *r,
3882                                       int snum)
3883 {
3884         WERROR result;
3885
3886         r->flags                = flags;
3887
3888         if (info2->comment == NULL || info2->comment[0] == '\0') {
3889                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
3890         } else {
3891                 r->comment      = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3892         }
3893         W_ERROR_HAVE_NO_MEMORY(r->comment);
3894
3895         result = create_printername(mem_ctx, servername, info2->printername, &r->name);
3896         if (!W_ERROR_IS_OK(result)) {
3897                 return result;
3898         }
3899
3900         r->description          = talloc_asprintf(mem_ctx, "%s,%s,%s",
3901                                                   r->name,
3902                                                   info2->drivername,
3903                                                   r->comment);
3904         W_ERROR_HAVE_NO_MEMORY(r->description);
3905
3906         return WERR_OK;
3907 }
3908
3909 /********************************************************************
3910  * construct_printer_info2
3911  * fill a spoolss_PrinterInfo2 struct
3912 ********************************************************************/
3913
3914 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3915                                       struct messaging_context *msg_ctx,
3916                                       const struct spoolss_PrinterInfo2 *info2,
3917                                       const char *servername,
3918                                       struct spoolss_PrinterInfo2 *r,
3919                                       int snum)
3920 {
3921         int count;
3922         print_status_struct status;
3923         WERROR result;
3924
3925         count = print_queue_length(msg_ctx, snum, &status);
3926
3927         if (servername) {
3928                 r->servername           = talloc_strdup(mem_ctx, servername);
3929                 W_ERROR_HAVE_NO_MEMORY(r->servername);
3930         } else {
3931                 r->servername           = NULL;
3932         }
3933
3934         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3935         if (!W_ERROR_IS_OK(result)) {
3936                 return result;
3937         }
3938
3939         r->sharename            = talloc_strdup(mem_ctx, lp_servicename(snum));
3940         W_ERROR_HAVE_NO_MEMORY(r->sharename);
3941         r->portname             = talloc_strdup(mem_ctx, info2->portname);
3942         W_ERROR_HAVE_NO_MEMORY(r->portname);
3943         r->drivername           = talloc_strdup(mem_ctx, info2->drivername);
3944         W_ERROR_HAVE_NO_MEMORY(r->drivername);
3945
3946         if (info2->comment[0] == '\0') {
3947                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
3948         } else {
3949                 r->comment      = talloc_strdup(mem_ctx, info2->comment);
3950         }
3951         W_ERROR_HAVE_NO_MEMORY(r->comment);
3952
3953         r->location             = talloc_strdup(mem_ctx, info2->location);
3954         W_ERROR_HAVE_NO_MEMORY(r->location);
3955         r->sepfile              = talloc_strdup(mem_ctx, info2->sepfile);
3956         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
3957         r->printprocessor       = talloc_strdup(mem_ctx, info2->printprocessor);
3958         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
3959         r->datatype             = talloc_strdup(mem_ctx, info2->datatype);
3960         W_ERROR_HAVE_NO_MEMORY(r->datatype);
3961         r->parameters           = talloc_strdup(mem_ctx, info2->parameters);
3962         W_ERROR_HAVE_NO_MEMORY(r->parameters);
3963
3964         r->attributes           = info2->attributes;
3965
3966         r->priority             = info2->priority;
3967         r->defaultpriority      = info2->defaultpriority;
3968         r->starttime            = info2->starttime;
3969         r->untiltime            = info2->untiltime;
3970         r->status               = nt_printq_status(status.status);
3971         r->cjobs                = count;
3972         r->averageppm           = info2->averageppm;
3973
3974         copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
3975         if (!r->devmode) {
3976                 DEBUG(8,("Returning NULL Devicemode!\n"));
3977         }
3978
3979         compose_devicemode_devicename(r->devmode, r->printername);
3980
3981         r->secdesc = NULL;
3982
3983         if (info2->secdesc != NULL) {
3984                 /* don't use talloc_steal() here unless you do a deep steal of all
3985                    the SEC_DESC members */
3986
3987                 r->secdesc      = dup_sec_desc(mem_ctx, info2->secdesc);
3988         }
3989
3990         return WERR_OK;
3991 }
3992
3993 /********************************************************************
3994  * construct_printer_info3
3995  * fill a spoolss_PrinterInfo3 struct
3996  ********************************************************************/
3997
3998 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
3999                                       const struct spoolss_PrinterInfo2 *info2,
4000                                       const char *servername,
4001                                       struct spoolss_PrinterInfo3 *r,
4002                                       int snum)
4003 {
4004         /* These are the components of the SD we are returning. */
4005
4006         if (info2->secdesc != NULL) {
4007                 /* don't use talloc_steal() here unless you do a deep steal of all
4008                    the SEC_DESC members */
4009
4010                 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4011                 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
4012         }
4013
4014         return WERR_OK;
4015 }
4016
4017 /********************************************************************
4018  * construct_printer_info4
4019  * fill a spoolss_PrinterInfo4 struct
4020  ********************************************************************/
4021
4022 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4023                                       const struct spoolss_PrinterInfo2 *info2,
4024                                       const char *servername,
4025                                       struct spoolss_PrinterInfo4 *r,
4026                                       int snum)
4027 {
4028         WERROR result;
4029
4030         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4031         if (!W_ERROR_IS_OK(result)) {
4032                 return result;
4033         }
4034
4035         if (servername) {
4036                 r->servername   = talloc_strdup(mem_ctx, servername);
4037                 W_ERROR_HAVE_NO_MEMORY(r->servername);
4038         } else {
4039                 r->servername = NULL;
4040         }
4041
4042         r->attributes   = info2->attributes;
4043
4044         return WERR_OK;
4045 }
4046
4047 /********************************************************************
4048  * construct_printer_info5
4049  * fill a spoolss_PrinterInfo5 struct
4050  ********************************************************************/
4051
4052 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4053                                       const struct spoolss_PrinterInfo2 *info2,
4054                                       const char *servername,
4055                                       struct spoolss_PrinterInfo5 *r,
4056                                       int snum)
4057 {
4058         WERROR result;
4059
4060         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4061         if (!W_ERROR_IS_OK(result)) {
4062                 return result;
4063         }
4064
4065         r->portname     = talloc_strdup(mem_ctx, info2->portname);
4066         W_ERROR_HAVE_NO_MEMORY(r->portname);
4067
4068         r->attributes   = info2->attributes;
4069
4070         /* these two are not used by NT+ according to MSDN */
4071         r->device_not_selected_timeout          = 0x0;  /* have seen 0x3a98 */
4072         r->transmission_retry_timeout           = 0x0;  /* have seen 0xafc8 */
4073
4074         return WERR_OK;
4075 }
4076
4077 /********************************************************************
4078  * construct_printer_info_6
4079  * fill a spoolss_PrinterInfo6 struct
4080  ********************************************************************/
4081
4082 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4083                                       struct messaging_context *msg_ctx,
4084                                       const struct spoolss_PrinterInfo2 *info2,
4085                                       const char *servername,
4086                                       struct spoolss_PrinterInfo6 *r,
4087                                       int snum)
4088 {
4089         int count;
4090         print_status_struct status;
4091
4092         count = print_queue_length(msg_ctx, snum, &status);
4093
4094         r->status = nt_printq_status(status.status);
4095
4096         return WERR_OK;
4097 }
4098
4099 /********************************************************************
4100  * construct_printer_info7
4101  * fill a spoolss_PrinterInfo7 struct
4102  ********************************************************************/
4103
4104 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4105                                       struct messaging_context *msg_ctx,
4106                                       const char *servername,
4107                                       struct spoolss_PrinterInfo7 *r,
4108                                       int snum)
4109 {
4110         struct auth_serversupplied_info *server_info;
4111         struct GUID guid;
4112         NTSTATUS status;
4113
4114         status = make_server_info_system(mem_ctx, &server_info);
4115         if (!NT_STATUS_IS_OK(status)) {
4116                 DEBUG(0, ("construct_printer_info7: "
4117                           "Could not create system server_info\n"));
4118                 return WERR_NOMEM;
4119         }
4120
4121         if (is_printer_published(mem_ctx, server_info, msg_ctx,
4122                                  servername,
4123                                  lp_servicename(snum), &guid, NULL)) {
4124                 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4125                 r->action = DSPRINT_PUBLISH;
4126         } else {
4127                 r->guid = talloc_strdup(mem_ctx, "");
4128                 r->action = DSPRINT_UNPUBLISH;
4129         }
4130         W_ERROR_HAVE_NO_MEMORY(r->guid);
4131
4132         TALLOC_FREE(server_info);
4133         return WERR_OK;
4134 }
4135
4136 /********************************************************************
4137  * construct_printer_info8
4138  * fill a spoolss_PrinterInfo8 struct
4139  ********************************************************************/
4140
4141 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4142                                       const struct spoolss_PrinterInfo2 *info2,
4143                                       const char *servername,
4144                                       struct spoolss_DeviceModeInfo *r,
4145                                       int snum)
4146 {
4147         WERROR result;
4148         const char *printername;
4149
4150         result = create_printername(mem_ctx, servername, info2->printername, &printername);
4151         if (!W_ERROR_IS_OK(result)) {
4152                 return result;
4153         }
4154
4155         copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4156         if (!r->devmode) {
4157                 DEBUG(8,("Returning NULL Devicemode!\n"));
4158         }
4159
4160         compose_devicemode_devicename(r->devmode, printername);
4161
4162         return WERR_OK;
4163 }
4164
4165
4166 /********************************************************************
4167 ********************************************************************/
4168
4169 static bool snum_is_shared_printer(int snum)
4170 {
4171         return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4172 }
4173
4174 /********************************************************************
4175  Spoolss_enumprinters.
4176 ********************************************************************/
4177
4178 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4179                                            const struct auth_serversupplied_info *server_info,
4180                                            struct messaging_context *msg_ctx,
4181                                            const char *servername,
4182                                            uint32_t level,
4183                                            uint32_t flags,
4184                                            union spoolss_PrinterInfo **info_p,
4185                                            uint32_t *count_p)
4186 {
4187         int snum;
4188         int n_services = lp_numservices();
4189         union spoolss_PrinterInfo *info = NULL;
4190         uint32_t count = 0;
4191         WERROR result = WERR_OK;
4192
4193         *count_p = 0;
4194         *info_p = NULL;
4195
4196         for (snum = 0; snum < n_services; snum++) {
4197
4198                 const char *printer;
4199                 struct spoolss_PrinterInfo2 *info2;
4200
4201                 if (!snum_is_shared_printer(snum)) {
4202                         continue;
4203                 }
4204
4205                 printer = lp_const_servicename(snum);
4206
4207                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4208                         printer, snum));
4209
4210                 result = winreg_create_printer(mem_ctx,
4211                                                server_info,
4212                                                msg_ctx,
4213                                                printer);
4214                 if (!W_ERROR_IS_OK(result)) {
4215                         goto out;
4216                 }
4217
4218                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4219                                             union spoolss_PrinterInfo,
4220                                             count + 1);
4221                 if (!info) {
4222                         result = WERR_NOMEM;
4223                         goto out;
4224                 }
4225
4226                 result = winreg_get_printer(mem_ctx, server_info, msg_ctx,
4227                                             printer, &info2);
4228                 if (!W_ERROR_IS_OK(result)) {
4229                         goto out;
4230                 }
4231
4232                 switch (level) {
4233                 case 0:
4234                         result = construct_printer_info0(info, server_info,
4235                                                          msg_ctx, info2,
4236                                                          servername,
4237                                                          &info[count].info0, snum);
4238                         break;
4239                 case 1:
4240                         result = construct_printer_info1(info, info2, flags,
4241                                                          servername,
4242                                                          &info[count].info1, snum);
4243                         break;
4244                 case 2:
4245                         result = construct_printer_info2(info, msg_ctx, info2,
4246                                                          servername,
4247                                                          &info[count].info2, snum);
4248                         break;
4249                 case 4:
4250                         result = construct_printer_info4(info, info2,
4251                                                          servername,
4252                                                          &info[count].info4, snum);
4253                         break;
4254                 case 5:
4255                         result = construct_printer_info5(info, info2,
4256                                                          servername,
4257                                                          &info[count].info5, snum);
4258                         break;
4259
4260                 default:
4261                         result = WERR_UNKNOWN_LEVEL;
4262                         goto out;
4263                 }
4264
4265                 if (!W_ERROR_IS_OK(result)) {
4266                         goto out;
4267                 }
4268
4269                 count++;
4270         }
4271
4272         *count_p = count;
4273         *info_p = info;
4274
4275  out:
4276         if (!W_ERROR_IS_OK(result)) {
4277                 TALLOC_FREE(info);
4278                 return result;
4279         }
4280
4281         *info_p = info;
4282
4283         return WERR_OK;
4284 }
4285
4286 /********************************************************************
4287  * handle enumeration of printers at level 0
4288  ********************************************************************/
4289
4290 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4291                                   const struct auth_serversupplied_info *server_info,
4292                                   struct messaging_context *msg_ctx,
4293                                   uint32_t flags,
4294                                   const char *servername,
4295                                   union spoolss_PrinterInfo **info,
4296                                   uint32_t *count)
4297 {
4298         DEBUG(4,("enum_all_printers_info_0\n"));
4299
4300         return enum_all_printers_info_level(mem_ctx, server_info, msg_ctx,
4301                                             servername, 0, flags, info, count);
4302 }
4303
4304
4305 /********************************************************************
4306 ********************************************************************/
4307
4308 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4309                                        const struct auth_serversupplied_info *server_info,
4310                                        struct messaging_context *msg_ctx,
4311                                        const char *servername,
4312                                        uint32_t flags,
4313                                        union spoolss_PrinterInfo **info,
4314                                        uint32_t *count)
4315 {
4316         DEBUG(4,("enum_all_printers_info_1\n"));
4317
4318         return enum_all_printers_info_level(mem_ctx, server_info, msg_ctx,
4319                                             servername, 1, flags, info, count);
4320 }
4321
4322 /********************************************************************
4323  enum_all_printers_info_1_local.
4324 *********************************************************************/
4325
4326 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4327                                              const struct auth_serversupplied_info *server_info,
4328                                              struct messaging_context *msg_ctx,
4329                                              const char *servername,
4330                                              union spoolss_PrinterInfo **info,
4331                                              uint32_t *count)
4332 {
4333         DEBUG(4,("enum_all_printers_info_1_local\n"));
4334
4335         return enum_all_printers_info_1(mem_ctx, server_info, msg_ctx,
4336                                         servername, PRINTER_ENUM_ICON8, info, count);
4337 }
4338
4339 /********************************************************************
4340  enum_all_printers_info_1_name.
4341 *********************************************************************/
4342
4343 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4344                                             const struct auth_serversupplied_info *server_info,
4345                                             struct messaging_context *msg_ctx,
4346                                             const char *servername,
4347                                             union spoolss_PrinterInfo **info,
4348                                             uint32_t *count)
4349 {
4350         const char *s = servername;
4351
4352         DEBUG(4,("enum_all_printers_info_1_name\n"));
4353
4354         if ((servername[0] == '\\') && (servername[1] == '\\')) {
4355                 s = servername + 2;
4356         }
4357
4358         if (!is_myname_or_ipaddr(s)) {
4359                 return WERR_INVALID_NAME;
4360         }
4361
4362         return enum_all_printers_info_1(mem_ctx, server_info, msg_ctx,
4363                                         servername, PRINTER_ENUM_ICON8, info, count);
4364 }
4365
4366 /********************************************************************
4367  enum_all_printers_info_1_network.
4368 *********************************************************************/
4369
4370 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4371                                                const struct auth_serversupplied_info *server_info,
4372                                                struct messaging_context *msg_ctx,
4373                                                const char *servername,
4374                                                union spoolss_PrinterInfo **info,
4375                                                uint32_t *count)
4376 {
4377         const char *s = servername;
4378
4379         DEBUG(4,("enum_all_printers_info_1_network\n"));
4380
4381         /* If we respond to a enum_printers level 1 on our name with flags
4382            set to PRINTER_ENUM_REMOTE with a list of printers then these
4383            printers incorrectly appear in the APW browse list.
4384            Specifically the printers for the server appear at the workgroup
4385            level where all the other servers in the domain are
4386            listed. Windows responds to this call with a
4387            WERR_CAN_NOT_COMPLETE so we should do the same. */
4388
4389         if (servername[0] == '\\' && servername[1] == '\\') {
4390                  s = servername + 2;
4391         }
4392
4393         if (is_myname_or_ipaddr(s)) {
4394                  return WERR_CAN_NOT_COMPLETE;
4395         }
4396
4397         return enum_all_printers_info_1(mem_ctx, server_info, msg_ctx,
4398                                         servername, PRINTER_ENUM_NAME, info, count);
4399 }
4400
4401 /********************************************************************
4402  * api_spoolss_enumprinters
4403  *
4404  * called from api_spoolss_enumprinters (see this to understand)
4405  ********************************************************************/
4406
4407 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4408                                        const struct auth_serversupplied_info *server_info,
4409                                        struct messaging_context *msg_ctx,
4410                                        const char *servername,
4411                                        union spoolss_PrinterInfo **info,
4412                                        uint32_t *count)
4413 {
4414         DEBUG(4,("enum_all_printers_info_2\n"));
4415
4416         return enum_all_printers_info_level(mem_ctx, server_info, msg_ctx,
4417                                             servername, 2, 0, info, count);
4418 }
4419
4420 /********************************************************************
4421  * handle enumeration of printers at level 1
4422  ********************************************************************/
4423
4424 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4425                                   const struct auth_serversupplied_info *server_info,
4426                                   struct messaging_context *msg_ctx,
4427                                   uint32_t flags,
4428                                   const char *servername,
4429                                   union spoolss_PrinterInfo **info,
4430                                   uint32_t *count)
4431 {
4432         /* Not all the flags are equals */
4433
4434         if (flags & PRINTER_ENUM_LOCAL) {
4435                 return enum_all_printers_info_1_local(mem_ctx, server_info,
4436                                                       msg_ctx, servername, info, count);
4437         }
4438
4439         if (flags & PRINTER_ENUM_NAME) {
4440                 return enum_all_printers_info_1_name(mem_ctx, server_info,
4441                                                      msg_ctx, servername, info,
4442                                                      count);
4443         }
4444
4445         if (flags & PRINTER_ENUM_NETWORK) {
4446                 return enum_all_printers_info_1_network(mem_ctx, server_info,
4447                                                         msg_ctx, servername, info,
4448                                                         count);
4449         }
4450
4451         return WERR_OK; /* NT4sp5 does that */
4452 }
4453
4454 /********************************************************************
4455  * handle enumeration of printers at level 2
4456  ********************************************************************/
4457
4458 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4459                                   const struct auth_serversupplied_info *server_info,
4460                                   struct messaging_context *msg_ctx,
4461                                   uint32_t flags,
4462                                   const char *servername,
4463                                   union spoolss_PrinterInfo **info,
4464                                   uint32_t *count)
4465 {
4466         if (flags & PRINTER_ENUM_LOCAL) {
4467
4468                 return enum_all_printers_info_2(mem_ctx, server_info, msg_ctx,
4469                                                 servername,
4470                                                 info, count);
4471         }
4472
4473         if (flags & PRINTER_ENUM_NAME) {
4474                 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4475                         return WERR_INVALID_NAME;
4476                 }
4477
4478                 return enum_all_printers_info_2(mem_ctx, server_info, msg_ctx,
4479                                                 servername,
4480                                                 info, count);
4481         }
4482
4483         if (flags & PRINTER_ENUM_REMOTE) {
4484                 return WERR_UNKNOWN_LEVEL;
4485         }
4486
4487         return WERR_OK;
4488 }
4489
4490 /********************************************************************
4491  * handle enumeration of printers at level 4
4492  ********************************************************************/
4493
4494 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4495                                   const struct auth_serversupplied_info *server_info,
4496                                   struct messaging_context *msg_ctx,
4497                                   uint32_t flags,
4498                                   const char *servername,
4499                                   union spoolss_PrinterInfo **info,
4500                                   uint32_t *count)
4501 {
4502         DEBUG(4,("enum_all_printers_info_4\n"));
4503
4504         return enum_all_printers_info_level(mem_ctx, server_info, msg_ctx,
4505                                             servername, 4, flags, info, count);
4506 }
4507
4508
4509 /********************************************************************
4510  * handle enumeration of printers at level 5
4511  ********************************************************************/
4512
4513 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4514                                   const struct auth_serversupplied_info *server_info,
4515                                   struct messaging_context *msg_ctx,
4516                                   uint32_t flags,
4517                                   const char *servername,
4518                                   union spoolss_PrinterInfo **info,
4519                                   uint32_t *count)
4520 {
4521         DEBUG(4,("enum_all_printers_info_5\n"));
4522
4523         return enum_all_printers_info_level(mem_ctx, server_info, msg_ctx,
4524                                             servername, 5, flags, info, count);
4525 }
4526
4527 /****************************************************************
4528  _spoolss_EnumPrinters
4529 ****************************************************************/
4530
4531 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4532                              struct spoolss_EnumPrinters *r)
4533 {
4534         const struct auth_serversupplied_info *server_info = get_server_info_system();
4535         WERROR result;
4536
4537         /* that's an [in out] buffer */
4538
4539         if (!r->in.buffer && (r->in.offered != 0)) {
4540                 return WERR_INVALID_PARAM;
4541         }
4542
4543         DEBUG(4,("_spoolss_EnumPrinters\n"));
4544
4545         *r->out.needed = 0;
4546         *r->out.count = 0;
4547         *r->out.info = NULL;
4548
4549         /*
4550          * Level 1:
4551          *          flags==PRINTER_ENUM_NAME
4552          *           if name=="" then enumerates all printers
4553          *           if name!="" then enumerate the printer
4554          *          flags==PRINTER_ENUM_REMOTE
4555          *          name is NULL, enumerate printers
4556          * Level 2: name!="" enumerates printers, name can't be NULL
4557          * Level 3: doesn't exist
4558          * Level 4: does a local registry lookup
4559          * Level 5: same as Level 2
4560          */
4561
4562         if (r->in.server && r->in.server[0] == '\0') {
4563                 r->in.server = NULL;
4564         }
4565
4566         switch (r->in.level) {
4567         case 0:
4568                 result = enumprinters_level0(p->mem_ctx, server_info,
4569                                              p->msg_ctx, r->in.flags,
4570                                              r->in.server,
4571                                              r->out.info, r->out.count);
4572                 break;
4573         case 1:
4574                 result = enumprinters_level1(p->mem_ctx, server_info,
4575                                              p->msg_ctx, r->in.flags,
4576                                              r->in.server,
4577                                              r->out.info, r->out.count);
4578                 break;
4579         case 2:
4580                 result = enumprinters_level2(p->mem_ctx, server_info,
4581                                              p->msg_ctx, r->in.flags,
4582                                              r->in.server,
4583                                              r->out.info, r->out.count);
4584                 break;
4585         case 4:
4586                 result = enumprinters_level4(p->mem_ctx, server_info,
4587                                              p->msg_ctx, r->in.flags,
4588                                              r->in.server,
4589                                              r->out.info, r->out.count);
4590                 break;
4591         case 5:
4592                 result = enumprinters_level5(p->mem_ctx, server_info,
4593                                              p->msg_ctx, r->in.flags,
4594                                              r->in.server,
4595                                              r->out.info, r->out.count);
4596                 break;
4597         default:
4598                 return WERR_UNKNOWN_LEVEL;
4599         }
4600
4601         if (!W_ERROR_IS_OK(result)) {
4602                 return result;
4603         }
4604
4605         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4606                                                      spoolss_EnumPrinters, 
4607                                                      *r->out.info, r->in.level,
4608                                                      *r->out.count);
4609         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4610         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4611
4612         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4613 }
4614
4615 /****************************************************************
4616  _spoolss_GetPrinter
4617 ****************************************************************/
4618
4619 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4620                            struct spoolss_GetPrinter *r)
4621 {
4622         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4623         struct spoolss_PrinterInfo2 *info2 = NULL;
4624         WERROR result = WERR_OK;
4625         int snum;
4626
4627         /* that's an [in out] buffer */
4628
4629         if (!r->in.buffer && (r->in.offered != 0)) {
4630                 return WERR_INVALID_PARAM;
4631         }
4632
4633         *r->out.needed = 0;
4634
4635         if (Printer == NULL) {
4636                 return WERR_BADFID;
4637         }
4638
4639         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4640                 return WERR_BADFID;
4641         }
4642
4643         result = winreg_get_printer(p->mem_ctx,
4644                                     get_server_info_system(),
4645                                     p->msg_ctx,
4646                                     lp_const_servicename(snum),
4647                                     &info2);
4648         if (!W_ERROR_IS_OK(result)) {
4649                 goto out;
4650         }
4651
4652         switch (r->in.level) {
4653         case 0:
4654                 result = construct_printer_info0(p->mem_ctx,
4655                                                  get_server_info_system(),
4656                                                  p->msg_ctx,
4657                                                  info2,
4658                                                  Printer->servername,
4659                                                  &r->out.info->info0,
4660                                                  snum);
4661                 break;
4662         case 1:
4663                 result = construct_printer_info1(p->mem_ctx, info2,
4664                                                  PRINTER_ENUM_ICON8,
4665                                                  Printer->servername,
4666                                                  &r->out.info->info1, snum);
4667                 break;
4668         case 2:
4669                 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4670                                                  Printer->servername,
4671                                                  &r->out.info->info2, snum);
4672                 break;
4673         case 3:
4674                 result = construct_printer_info3(p->mem_ctx, info2,
4675                                                  Printer->servername,
4676                                                  &r->out.info->info3, snum);
4677                 break;
4678         case 4:
4679                 result = construct_printer_info4(p->mem_ctx, info2,
4680                                                  Printer->servername,
4681                                                  &r->out.info->info4, snum);
4682                 break;
4683         case 5:
4684                 result = construct_printer_info5(p->mem_ctx, info2,
4685                                                  Printer->servername,
4686                                                  &r->out.info->info5, snum);
4687                 break;
4688         case 6:
4689                 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4690                                                  Printer->servername,
4691                                                  &r->out.info->info6, snum);
4692                 break;
4693         case 7:
4694                 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4695                                                  Printer->servername,
4696                                                  &r->out.info->info7, snum);
4697                 break;
4698         case 8:
4699                 result = construct_printer_info8(p->mem_ctx, info2,
4700                                                  Printer->servername,
4701                                                  &r->out.info->info8, snum);
4702                 break;
4703         default:
4704                 result = WERR_UNKNOWN_LEVEL;
4705                 break;
4706         }
4707
4708  out:
4709         if (!W_ERROR_IS_OK(result)) {
4710                 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4711                           r->in.level, win_errstr(result)));
4712                 TALLOC_FREE(r->out.info);
4713                 return result;
4714         }
4715
4716         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo, 
4717                                                r->out.info, r->in.level);
4718         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4719
4720         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4721 }
4722
4723 /********************************************************************
4724  ********************************************************************/
4725
4726 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4727         do { \
4728                 if (in && strlen(in)) { \
4729                         out = talloc_strdup(mem_ctx, in); \
4730                 } else { \
4731                         out = talloc_strdup(mem_ctx, ""); \
4732                 } \
4733                 W_ERROR_HAVE_NO_MEMORY(out); \
4734         } while (0);
4735
4736 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4737         do { \
4738                 if (in && strlen(in)) { \
4739                         out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4740                 } else { \
4741                         out = talloc_strdup(mem_ctx, ""); \
4742                 } \
4743                 W_ERROR_HAVE_NO_MEMORY(out); \
4744         } while (0);
4745
4746 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4747                                                   const char **string_array,
4748                                                   const char ***presult,
4749                                                   const char *cservername,
4750                                                   const char *arch,
4751                                                   int version)
4752 {
4753         int i, num_strings = 0;
4754         const char **array = NULL;
4755
4756         if (string_array == NULL) {
4757                 return WERR_INVALID_PARAMETER;;
4758         }
4759
4760         for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4761                 const char *str = NULL;
4762
4763                 if (cservername == NULL || arch == NULL) {
4764                         FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4765                 } else {
4766                         FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4767                 }
4768
4769                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4770                         TALLOC_FREE(array);
4771                         return WERR_NOMEM;
4772                 }
4773         }
4774
4775         if (i > 0) {
4776                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4777                              &array, &num_strings);
4778         }
4779
4780         if (presult) {
4781                 *presult = array;
4782         }
4783
4784         return WERR_OK;
4785 }
4786
4787 /********************************************************************
4788  * fill a spoolss_DriverInfo1 struct
4789  ********************************************************************/
4790
4791 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4792                                         struct spoolss_DriverInfo1 *r,
4793                                         const struct spoolss_DriverInfo8 *driver,
4794                                         const char *servername)
4795 {
4796         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4797         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4798
4799         return WERR_OK;
4800 }
4801
4802 /********************************************************************
4803  * fill a spoolss_DriverInfo2 struct
4804  ********************************************************************/
4805
4806 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4807                                         struct spoolss_DriverInfo2 *r,
4808                                         const struct spoolss_DriverInfo8 *driver,
4809                                         const char *servername)
4810
4811 {
4812         const char *cservername = canon_servername(servername);
4813
4814         r->version              = driver->version;
4815
4816         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4817         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4818         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4819         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4820
4821         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4822                                driver->architecture,
4823                                driver->version,
4824                                driver->driver_path,
4825                                r->driver_path);
4826
4827         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4828                                driver->architecture,
4829                                driver->version,
4830                                driver->data_file,
4831                                r->data_file);
4832
4833         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4834                                driver->architecture,
4835                                driver->version,
4836                                driver->config_file,
4837                                r->config_file);
4838
4839         return WERR_OK;
4840 }
4841
4842 /********************************************************************
4843  * fill a spoolss_DriverInfo3 struct
4844  ********************************************************************/
4845
4846 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4847                                         struct spoolss_DriverInfo3 *r,
4848                                         const struct spoolss_DriverInfo8 *driver,
4849                                         const char *servername)
4850 {
4851         const char *cservername = canon_servername(servername);
4852
4853         r->version              = driver->version;
4854
4855         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4856         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4857         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4858         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4859
4860         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4861                                driver->architecture,
4862                                driver->version,
4863                                driver->driver_path,
4864                                r->driver_path);
4865
4866         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4867                                driver->architecture,
4868                                driver->version,
4869                                driver->data_file,
4870                                r->data_file);
4871
4872         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4873                                driver->architecture,
4874                                driver->version,
4875                                driver->config_file,
4876                                r->config_file);
4877
4878         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4879                                driver->architecture,
4880                                driver->version,
4881                                driver->help_file,
4882                                r->help_file);
4883
4884         FILL_DRIVER_STRING(mem_ctx,
4885                            driver->monitor_name,
4886                            r->monitor_name);
4887
4888         FILL_DRIVER_STRING(mem_ctx,
4889                            driver->default_datatype,
4890                            r->default_datatype);
4891
4892         return string_array_from_driver_info(mem_ctx,
4893                                              driver->dependent_files,
4894                                              &r->dependent_files,
4895                                              cservername,
4896                                              driver->architecture,
4897                                              driver->version);
4898 }
4899
4900 /********************************************************************
4901  * fill a spoolss_DriverInfo4 struct
4902  ********************************************************************/
4903
4904 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4905                                         struct spoolss_DriverInfo4 *r,
4906                                         const struct spoolss_DriverInfo8 *driver,
4907                                         const char *servername)
4908 {
4909         const char *cservername = canon_servername(servername);
4910         WERROR result;
4911
4912         r->version              = driver->version;
4913
4914         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4915         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4916         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4917         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4918
4919         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4920                                driver->architecture,
4921                                driver->version,
4922                                driver->driver_path,
4923                                r->driver_path);
4924
4925         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4926                                driver->architecture,
4927                                driver->version,
4928                                driver->data_file,
4929                                r->data_file);
4930
4931         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4932                                driver->architecture,
4933                                driver->version,
4934                                driver->config_file,
4935                                r->config_file);
4936
4937         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4938                                driver->architecture,
4939                                driver->version,
4940                                driver->help_file,
4941                                r->help_file);
4942
4943         result = string_array_from_driver_info(mem_ctx,
4944                                                driver->dependent_files,
4945                                                &r->dependent_files,
4946                                                cservername,
4947                                                driver->architecture,
4948                                                driver->version);
4949         if (!W_ERROR_IS_OK(result)) {
4950                 return result;
4951         }
4952
4953         FILL_DRIVER_STRING(mem_ctx,
4954                            driver->monitor_name,
4955                            r->monitor_name);
4956
4957         FILL_DRIVER_STRING(mem_ctx,
4958                            driver->default_datatype,
4959                            r->default_datatype);
4960
4961
4962         result = string_array_from_driver_info(mem_ctx,
4963                                                driver->previous_names,
4964                                                &r->previous_names,
4965                                                NULL, NULL, 0);
4966
4967         return result;
4968 }
4969
4970 /********************************************************************
4971  * fill a spoolss_DriverInfo5 struct
4972  ********************************************************************/
4973
4974 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
4975                                         struct spoolss_DriverInfo5 *r,
4976                                         const struct spoolss_DriverInfo8 *driver,
4977                                         const char *servername)
4978 {
4979         const char *cservername = canon_servername(servername);
4980
4981         r->version              = driver->version;
4982
4983         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4984         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4985         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4986         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4987
4988         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4989                                driver->architecture,
4990                                driver->version,
4991                                driver->driver_path,
4992                                r->driver_path);
4993
4994         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4995                                driver->architecture,
4996                                driver->version,
4997                                driver->data_file,
4998                                r->data_file);
4999
5000         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5001                                driver->architecture,
5002                                driver->version,
5003                                driver->config_file,
5004                                r->config_file);
5005
5006         r->driver_attributes    = 0;
5007         r->config_version       = 0;
5008         r->driver_version       = 0;
5009
5010         return WERR_OK;
5011 }
5012 /********************************************************************
5013  * fill a spoolss_DriverInfo6 struct
5014  ********************************************************************/
5015
5016 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5017                                         struct spoolss_DriverInfo6 *r,
5018                                         const struct spoolss_DriverInfo8 *driver,
5019                                         const char *servername)
5020 {
5021         const char *cservername = canon_servername(servername);
5022         WERROR result;
5023
5024         r->version              = driver->version;
5025
5026         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5027         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5028         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5029         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5030
5031         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5032                                driver->architecture,
5033                                driver->version,
5034                                driver->driver_path,
5035                                r->driver_path);
5036
5037         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5038                                driver->architecture,
5039                                driver->version,
5040                                driver->data_file,
5041                                r->data_file);
5042
5043         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5044                                driver->architecture,
5045                                driver->version,
5046                                driver->config_file,
5047                                r->config_file);
5048
5049         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5050                                driver->architecture,
5051                                driver->version,
5052                                driver->help_file,
5053                                r->help_file);
5054
5055         FILL_DRIVER_STRING(mem_ctx,
5056                            driver->monitor_name,
5057                            r->monitor_name);
5058
5059         FILL_DRIVER_STRING(mem_ctx,
5060                            driver->default_datatype,
5061                            r->default_datatype);
5062
5063         result = string_array_from_driver_info(mem_ctx,
5064                                                driver->dependent_files,
5065                                                &r->dependent_files,
5066                                                cservername,
5067                                                driver->architecture,
5068                                                driver->version);
5069         if (!W_ERROR_IS_OK(result)) {
5070                 return result;
5071         }
5072
5073         result = string_array_from_driver_info(mem_ctx,
5074                                                driver->previous_names,
5075                                                &r->previous_names,
5076                                                NULL, NULL, 0);
5077         if (!W_ERROR_IS_OK(result)) {
5078                 return result;
5079         }
5080
5081         r->driver_date          = driver->driver_date;
5082         r->driver_version       = driver->driver_version;
5083
5084         FILL_DRIVER_STRING(mem_ctx,
5085                            driver->manufacturer_name,
5086                            r->manufacturer_name);
5087         FILL_DRIVER_STRING(mem_ctx,
5088                            driver->manufacturer_url,
5089                            r->manufacturer_url);
5090         FILL_DRIVER_STRING(mem_ctx,
5091                            driver->hardware_id,
5092                            r->hardware_id);
5093         FILL_DRIVER_STRING(mem_ctx,
5094                            driver->provider,
5095                            r->provider);
5096
5097         return WERR_OK;
5098 }
5099
5100 /********************************************************************
5101  * fill a spoolss_DriverInfo8 struct
5102  ********************************************************************/
5103
5104 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5105                                         struct spoolss_DriverInfo8 *r,
5106                                         const struct spoolss_DriverInfo8 *driver,
5107                                         const char *servername)
5108 {
5109         const char *cservername = canon_servername(servername);
5110         WERROR result;
5111
5112         r->version              = driver->version;
5113
5114         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5115         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5116         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5117         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5118
5119         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5120                                driver->architecture,
5121                                driver->version,
5122                                driver->driver_path,
5123                                r->driver_path);
5124
5125         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5126                                driver->architecture,
5127                                driver->version,
5128                                driver->data_file,
5129                                r->data_file);
5130
5131         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5132                                driver->architecture,
5133                                driver->version,
5134                                driver->config_file,
5135                                r->config_file);
5136
5137         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5138                                driver->architecture,
5139                                driver->version,
5140                                driver->help_file,
5141                                r->help_file);
5142
5143         FILL_DRIVER_STRING(mem_ctx,
5144                            driver->monitor_name,
5145                            r->monitor_name);
5146
5147         FILL_DRIVER_STRING(mem_ctx,
5148                            driver->default_datatype,
5149                            r->default_datatype);
5150
5151         result = string_array_from_driver_info(mem_ctx,
5152                                                driver->dependent_files,
5153                                                &r->dependent_files,
5154                                                cservername,
5155                                                driver->architecture,
5156                                                driver->version);
5157         if (!W_ERROR_IS_OK(result)) {
5158                 return result;
5159         }
5160
5161         result = string_array_from_driver_info(mem_ctx,
5162                                                driver->previous_names,
5163                                                &r->previous_names,
5164                                                NULL, NULL, 0);
5165         if (!W_ERROR_IS_OK(result)) {
5166                 return result;
5167         }
5168
5169         r->driver_date          = driver->driver_date;
5170         r->driver_version       = driver->driver_version;
5171
5172         FILL_DRIVER_STRING(mem_ctx,
5173                            driver->manufacturer_name,
5174                            r->manufacturer_name);
5175         FILL_DRIVER_STRING(mem_ctx,
5176                            driver->manufacturer_url,
5177                            r->manufacturer_url);
5178         FILL_DRIVER_STRING(mem_ctx,
5179                            driver->hardware_id,
5180                            r->hardware_id);
5181         FILL_DRIVER_STRING(mem_ctx,
5182                            driver->provider,
5183                            r->provider);
5184
5185         FILL_DRIVER_STRING(mem_ctx,
5186                            driver->print_processor,
5187                            r->print_processor);
5188         FILL_DRIVER_STRING(mem_ctx,
5189                            driver->vendor_setup,
5190                            r->vendor_setup);
5191
5192         result = string_array_from_driver_info(mem_ctx,
5193                                                driver->color_profiles,
5194                                                &r->color_profiles,
5195                                                NULL, NULL, 0);
5196         if (!W_ERROR_IS_OK(result)) {
5197                 return result;
5198         }
5199
5200         FILL_DRIVER_STRING(mem_ctx,
5201                            driver->inf_path,
5202                            r->inf_path);
5203
5204         r->printer_driver_attributes    = driver->printer_driver_attributes;
5205
5206         result = string_array_from_driver_info(mem_ctx,
5207                                                driver->core_driver_dependencies,
5208                                                &r->core_driver_dependencies,
5209                                                NULL, NULL, 0);
5210         if (!W_ERROR_IS_OK(result)) {
5211                 return result;
5212         }
5213
5214         r->min_inbox_driver_ver_date    = driver->min_inbox_driver_ver_date;
5215         r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5216
5217         return WERR_OK;
5218 }
5219
5220 #if 0 /* disabled until marshalling issues are resolved - gd */
5221 /********************************************************************
5222  ********************************************************************/
5223
5224 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5225                                           struct spoolss_DriverFileInfo *r,
5226                                           const char *cservername,
5227                                           const char *file_name,
5228                                           enum spoolss_DriverFileType file_type,
5229                                           uint32_t file_version)
5230 {
5231         r->file_name    = talloc_asprintf(mem_ctx, "\\\\%s%s",
5232                                           cservername, file_name);
5233         W_ERROR_HAVE_NO_MEMORY(r->file_name);
5234         r->file_type    = file_type;
5235         r->file_version = file_version;
5236
5237         return WERR_OK;
5238 }
5239
5240 /********************************************************************
5241  ********************************************************************/
5242
5243 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5244                                                  const struct spoolss_DriverInfo8 *driver,
5245                                                  const char *cservername,
5246                                                  struct spoolss_DriverFileInfo **info_p,
5247                                                  uint32_t *count_p)
5248 {
5249         struct spoolss_DriverFileInfo *info = NULL;
5250         uint32_t count = 0;
5251         WERROR result;
5252         uint32_t i;
5253
5254         *info_p = NULL;
5255         *count_p = 0;
5256
5257         if (strlen(driver->driver_path)) {
5258                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5259                                             struct spoolss_DriverFileInfo,
5260                                             count + 1);
5261                 W_ERROR_HAVE_NO_MEMORY(info);
5262                 result = fill_spoolss_DriverFileInfo(info,
5263                                                      &info[count],
5264                                                      cservername,
5265                                                      driver->driver_path,
5266                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5267                                                      0);
5268                 W_ERROR_NOT_OK_RETURN(result);
5269                 count++;
5270         }
5271
5272         if (strlen(driver->config_file)) {
5273                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5274                                             struct spoolss_DriverFileInfo,
5275                                             count + 1);
5276                 W_ERROR_HAVE_NO_MEMORY(info);
5277                 result = fill_spoolss_DriverFileInfo(info,
5278                                                      &info[count],
5279                                                      cservername,
5280                                                      driver->config_file,
5281                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5282                                                      0);
5283                 W_ERROR_NOT_OK_RETURN(result);
5284                 count++;
5285         }
5286
5287         if (strlen(driver->data_file)) {
5288                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5289                                             struct spoolss_DriverFileInfo,
5290                                             count + 1);
5291                 W_ERROR_HAVE_NO_MEMORY(info);
5292                 result = fill_spoolss_DriverFileInfo(info,
5293                                                      &info[count],
5294                                                      cservername,
5295                                                      driver->data_file,
5296                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
5297                                                      0);
5298                 W_ERROR_NOT_OK_RETURN(result);
5299                 count++;
5300         }
5301
5302         if (strlen(driver->help_file)) {
5303                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5304                                             struct spoolss_DriverFileInfo,
5305                                             count + 1);
5306                 W_ERROR_HAVE_NO_MEMORY(info);
5307                 result = fill_spoolss_DriverFileInfo(info,
5308                                                      &info[count],
5309                                                      cservername,
5310                                                      driver->help_file,
5311                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
5312                                                      0);
5313                 W_ERROR_NOT_OK_RETURN(result);
5314                 count++;
5315         }
5316
5317         for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5318                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5319                                             struct spoolss_DriverFileInfo,
5320                                             count + 1);
5321                 W_ERROR_HAVE_NO_MEMORY(info);
5322                 result = fill_spoolss_DriverFileInfo(info,
5323                                                      &info[count],
5324                                                      cservername,
5325                                                      driver->dependent_files[i],
5326                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5327                                                      0);
5328                 W_ERROR_NOT_OK_RETURN(result);
5329                 count++;
5330         }
5331
5332         *info_p = info;
5333         *count_p = count;
5334
5335         return WERR_OK;
5336 }
5337
5338 /********************************************************************
5339  * fill a spoolss_DriverInfo101 struct
5340  ********************************************************************/
5341
5342 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5343                                           struct spoolss_DriverInfo101 *r,
5344                                           const struct spoolss_DriverInfo8 *driver,
5345                                           const char *servername)
5346 {
5347         const char *cservername = canon_servername(servername);
5348         WERROR result;
5349
5350         r->version              = driver->version;
5351
5352         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5353         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5354         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5355         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5356
5357         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5358                                                     cservername,
5359                                                     &r->file_info,
5360                                                     &r->file_count);
5361         if (!W_ERROR_IS_OK(result)) {
5362                 return result;
5363         }
5364
5365         FILL_DRIVER_STRING(mem_ctx,
5366                            driver->monitor_name,
5367                            r->monitor_name);
5368
5369         FILL_DRIVER_STRING(mem_ctx,
5370                            driver->default_datatype,
5371                            r->default_datatype);
5372
5373         result = string_array_from_driver_info(mem_ctx,
5374                                                driver->previous_names,
5375                                                &r->previous_names,
5376                                                NULL, NULL, 0);
5377         if (!W_ERROR_IS_OK(result)) {
5378                 return result;
5379         }
5380
5381         r->driver_date          = driver->driver_date;
5382         r->driver_version       = driver->driver_version;
5383
5384         FILL_DRIVER_STRING(mem_ctx,
5385                            driver->manufacturer_name,
5386                            r->manufacturer_name);
5387         FILL_DRIVER_STRING(mem_ctx,
5388                            driver->manufacturer_url,
5389                            r->manufacturer_url);
5390         FILL_DRIVER_STRING(mem_ctx,
5391                            driver->hardware_id,
5392                            r->hardware_id);
5393         FILL_DRIVER_STRING(mem_ctx,
5394                            driver->provider,
5395                            r->provider);
5396
5397         return WERR_OK;
5398 }
5399 #endif
5400 /********************************************************************
5401  ********************************************************************/
5402
5403 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5404                                                   const struct auth_serversupplied_info *server_info,
5405                                                   struct messaging_context *msg_ctx,
5406                                                   uint32_t level,
5407                                                   union spoolss_DriverInfo *r,
5408                                                   int snum,
5409                                                   const char *servername,
5410                                                   const char *architecture,
5411                                                   uint32_t version)
5412 {
5413         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5414         struct spoolss_DriverInfo8 *driver;
5415         WERROR result;
5416
5417         if (level == 101) {
5418                 return WERR_UNKNOWN_LEVEL;
5419         }
5420
5421         result = winreg_get_printer(mem_ctx,
5422                                     server_info,
5423                                     msg_ctx,
5424                                     lp_const_servicename(snum),
5425                                     &pinfo2);
5426
5427         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5428                 win_errstr(result)));
5429
5430         if (!W_ERROR_IS_OK(result)) {
5431                 return WERR_INVALID_PRINTER_NAME;
5432         }
5433
5434         result = winreg_get_driver(mem_ctx, server_info, msg_ctx,
5435                                    architecture,
5436                                    pinfo2->drivername, version, &driver);
5437
5438         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5439                 win_errstr(result)));
5440
5441         if (!W_ERROR_IS_OK(result)) {
5442                 /*
5443                  * Is this a W2k client ?
5444                  */
5445
5446                 if (version < 3) {
5447                         talloc_free(pinfo2);
5448                         return WERR_UNKNOWN_PRINTER_DRIVER;
5449                 }
5450
5451                 /* Yes - try again with a WinNT driver. */
5452                 version = 2;
5453                 result = winreg_get_driver(mem_ctx, server_info, msg_ctx,
5454                                            architecture,
5455                                            pinfo2->drivername,
5456                                            version, &driver);
5457                 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5458                         win_errstr(result)));
5459                 if (!W_ERROR_IS_OK(result)) {
5460                         talloc_free(pinfo2);
5461                         return WERR_UNKNOWN_PRINTER_DRIVER;
5462                 }
5463         }
5464
5465         switch (level) {
5466         case 1:
5467                 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5468                 break;
5469         case 2:
5470                 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5471                 break;
5472         case 3:
5473                 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5474                 break;
5475         case 4:
5476                 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5477                 break;
5478         case 5:
5479                 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5480                 break;
5481         case 6:
5482                 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5483                 break;
5484         case 8:
5485                 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5486                 break;
5487 #if 0 /* disabled until marshalling issues are resolved - gd */
5488         case 101:
5489                 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5490                 break;
5491 #endif
5492         default:
5493                 result = WERR_UNKNOWN_LEVEL;
5494                 break;
5495         }
5496
5497         talloc_free(pinfo2);
5498         talloc_free(driver);
5499
5500         return result;
5501 }
5502
5503 /****************************************************************
5504  _spoolss_GetPrinterDriver2
5505 ****************************************************************/
5506
5507 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5508                                   struct spoolss_GetPrinterDriver2 *r)
5509 {
5510         struct printer_handle *printer;
5511         WERROR result;
5512
5513         int snum;
5514
5515         /* that's an [in out] buffer */
5516
5517         if (!r->in.buffer && (r->in.offered != 0)) {
5518                 return WERR_INVALID_PARAM;
5519         }
5520
5521         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5522
5523         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5524                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5525                 return WERR_INVALID_PRINTER_NAME;
5526         }
5527
5528         *r->out.needed = 0;
5529         *r->out.server_major_version = 0;
5530         *r->out.server_minor_version = 0;
5531
5532         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5533                 return WERR_BADFID;
5534         }
5535
5536         result = construct_printer_driver_info_level(p->mem_ctx,
5537                                                      get_server_info_system(),
5538                                                      p->msg_ctx,
5539                                                      r->in.level, r->out.info,
5540                                                      snum, printer->servername,
5541                                                      r->in.architecture,
5542                                                      r->in.client_major_version);
5543         if (!W_ERROR_IS_OK(result)) {
5544                 TALLOC_FREE(r->out.info);
5545                 return result;
5546         }
5547
5548         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo, 
5549                                                r->out.info, r->in.level);
5550         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5551
5552         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5553 }
5554
5555
5556 /****************************************************************
5557  _spoolss_StartPagePrinter
5558 ****************************************************************/
5559
5560 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5561                                  struct spoolss_StartPagePrinter *r)
5562 {
5563         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5564
5565         if (!Printer) {
5566                 DEBUG(3,("_spoolss_StartPagePrinter: "
5567                         "Error in startpageprinter printer handle\n"));
5568                 return WERR_BADFID;
5569         }
5570
5571         Printer->page_started = true;
5572         return WERR_OK;
5573 }
5574
5575 /****************************************************************
5576  _spoolss_EndPagePrinter
5577 ****************************************************************/
5578
5579 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5580                                struct spoolss_EndPagePrinter *r)
5581 {
5582         int snum;
5583
5584         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5585
5586         if (!Printer) {
5587                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5588                         OUR_HANDLE(r->in.handle)));
5589                 return WERR_BADFID;
5590         }
5591
5592         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5593                 return WERR_BADFID;
5594
5595         Printer->page_started = false;
5596         print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5597
5598         return WERR_OK;
5599 }
5600
5601 /****************************************************************
5602  _spoolss_StartDocPrinter
5603 ****************************************************************/
5604
5605 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5606                                 struct spoolss_StartDocPrinter *r)
5607 {
5608         struct spoolss_DocumentInfo1 *info_1;
5609         int snum;
5610         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5611         WERROR werr;
5612
5613         if (!Printer) {
5614                 DEBUG(2,("_spoolss_StartDocPrinter: "
5615                         "Invalid handle (%s:%u:%u)\n",
5616                         OUR_HANDLE(r->in.handle)));
5617                 return WERR_BADFID;
5618         }
5619
5620         if (Printer->jobid) {
5621                 DEBUG(2, ("_spoolss_StartDocPrinter: "
5622                           "StartDocPrinter called twice! "
5623                           "(existing jobid = %d)\n", Printer->jobid));
5624                 return WERR_INVALID_HANDLE;
5625         }
5626
5627         if (r->in.level != 1) {
5628                 return WERR_UNKNOWN_LEVEL;
5629         }
5630
5631         info_1 = r->in.info.info1;
5632
5633         /*
5634          * a nice thing with NT is it doesn't listen to what you tell it.
5635          * when asked to send _only_ RAW datas, it tries to send datas
5636          * in EMF format.
5637          *
5638          * So I add checks like in NT Server ...
5639          */
5640
5641         if (info_1->datatype) {
5642                 if (strcmp(info_1->datatype, "RAW") != 0) {
5643                         *r->out.job_id = 0;
5644                         return WERR_INVALID_DATATYPE;
5645                 }
5646         }
5647
5648         /* get the share number of the printer */
5649         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5650                 return WERR_BADFID;
5651         }
5652
5653         werr = print_job_start(p->server_info,
5654                                p->msg_ctx,
5655                                p->client_id->name,
5656                                snum,
5657                                info_1->document_name,
5658                                info_1->output_file,
5659                                Printer->devmode,
5660                                &Printer->jobid);
5661
5662         /* An error occured in print_job_start() so return an appropriate
5663            NT error code. */
5664
5665         if (!W_ERROR_IS_OK(werr)) {
5666                 return werr;
5667         }
5668
5669         Printer->document_started = true;
5670         *r->out.job_id = Printer->jobid;
5671
5672         return WERR_OK;
5673 }
5674
5675 /****************************************************************
5676  _spoolss_EndDocPrinter
5677 ****************************************************************/
5678
5679 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5680                               struct spoolss_EndDocPrinter *r)
5681 {
5682         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5683         NTSTATUS status;
5684         int snum;
5685
5686         if (!Printer) {
5687                 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5688                         OUR_HANDLE(r->in.handle)));
5689                 return WERR_BADFID;
5690         }
5691
5692         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5693                 return WERR_BADFID;
5694         }
5695
5696         Printer->document_started = false;
5697         status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5698         if (!NT_STATUS_IS_OK(status)) {
5699                 DEBUG(2, ("_spoolss_EndDocPrinter: "
5700                           "print_job_end failed [%s]\n",
5701                           nt_errstr(status)));
5702         }
5703
5704         Printer->jobid = 0;
5705         return ntstatus_to_werror(status);
5706 }
5707
5708 /****************************************************************
5709  _spoolss_WritePrinter
5710 ****************************************************************/
5711
5712 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5713                              struct spoolss_WritePrinter *r)
5714 {
5715         ssize_t buffer_written;
5716         int snum;
5717         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5718
5719         if (!Printer) {
5720                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5721                         OUR_HANDLE(r->in.handle)));
5722                 *r->out.num_written = r->in._data_size;
5723                 return WERR_BADFID;
5724         }
5725
5726         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5727                 return WERR_BADFID;
5728
5729         /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5730         buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5731                                                    snum, Printer->jobid,
5732                                                    (const char *)r->in.data.data,
5733                                                    (size_t)r->in._data_size);
5734         if (buffer_written == (ssize_t)-1) {
5735                 *r->out.num_written = 0;
5736                 if (errno == ENOSPC)
5737                         return WERR_NO_SPOOL_SPACE;
5738                 else
5739                         return WERR_ACCESS_DENIED;
5740         }
5741
5742         *r->out.num_written = r->in._data_size;
5743
5744         return WERR_OK;
5745 }
5746
5747 /********************************************************************
5748  * api_spoolss_getprinter
5749  * called from the spoolss dispatcher
5750  *
5751  ********************************************************************/
5752
5753 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5754                               struct pipes_struct *p)
5755 {
5756         const struct auth_serversupplied_info *server_info = p->server_info;
5757         int snum;
5758         WERROR errcode = WERR_BADFUNC;
5759         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5760
5761         if (!Printer) {
5762                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5763                         OUR_HANDLE(handle)));
5764                 return WERR_BADFID;
5765         }
5766
5767         if (!get_printer_snum(p, handle, &snum, NULL))
5768                 return WERR_BADFID;
5769
5770         switch (command) {
5771         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5772                 errcode = print_queue_pause(server_info, p->msg_ctx, snum);
5773                 break;
5774         case SPOOLSS_PRINTER_CONTROL_RESUME:
5775         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5776                 errcode = print_queue_resume(server_info, p->msg_ctx, snum);
5777                 break;
5778         case SPOOLSS_PRINTER_CONTROL_PURGE:
5779                 errcode = print_queue_purge(server_info, p->msg_ctx, snum);
5780                 break;
5781         default:
5782                 return WERR_UNKNOWN_LEVEL;
5783         }
5784
5785         return errcode;
5786 }
5787
5788
5789 /****************************************************************
5790  _spoolss_AbortPrinter
5791  * From MSDN: "Deletes printer's spool file if printer is configured
5792  * for spooling"
5793 ****************************************************************/
5794
5795 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
5796                              struct spoolss_AbortPrinter *r)
5797 {
5798         struct printer_handle   *Printer = find_printer_index_by_hnd(p, r->in.handle);
5799         int             snum;
5800         WERROR          errcode = WERR_OK;
5801
5802         if (!Printer) {
5803                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5804                         OUR_HANDLE(r->in.handle)));
5805                 return WERR_BADFID;
5806         }
5807
5808         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5809                 return WERR_BADFID;
5810
5811         if (!Printer->document_started) {
5812                 return WERR_SPL_NO_STARTDOC;
5813         }
5814
5815         errcode = print_job_delete(p->server_info,
5816                                    p->msg_ctx,
5817                                    snum,
5818                                    Printer->jobid);
5819
5820         return errcode;
5821 }
5822
5823 /********************************************************************
5824  * called by spoolss_api_setprinter
5825  * when updating a printer description
5826  ********************************************************************/
5827
5828 static WERROR update_printer_sec(struct policy_handle *handle,
5829                                  struct pipes_struct *p,
5830                                  struct sec_desc_buf *secdesc_ctr)
5831 {
5832         struct spoolss_security_descriptor *new_secdesc = NULL;
5833         struct spoolss_security_descriptor *old_secdesc = NULL;
5834         const char *printer;
5835         WERROR result;
5836         int snum;
5837
5838         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5839
5840         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5841                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5842                          OUR_HANDLE(handle)));
5843
5844                 result = WERR_BADFID;
5845                 goto done;
5846         }
5847
5848         if (secdesc_ctr == NULL) {
5849                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5850                 result = WERR_INVALID_PARAM;
5851                 goto done;
5852         }
5853         printer = lp_const_servicename(snum);
5854
5855         /* Check the user has permissions to change the security
5856            descriptor.  By experimentation with two NT machines, the user
5857            requires Full Access to the printer to change security
5858            information. */
5859
5860         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5861                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5862                 result = WERR_ACCESS_DENIED;
5863                 goto done;
5864         }
5865
5866         /* NT seems to like setting the security descriptor even though
5867            nothing may have actually changed. */
5868         result = winreg_get_printer_secdesc(p->mem_ctx,
5869                                             get_server_info_system(),
5870                                             p->msg_ctx,
5871                                             printer,
5872                                             &old_secdesc);
5873         if (!W_ERROR_IS_OK(result)) {
5874                 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc() failed\n"));
5875                 result = WERR_BADFID;
5876                 goto done;
5877         }
5878
5879         if (DEBUGLEVEL >= 10) {
5880                 struct security_acl *the_acl;
5881                 int i;
5882
5883                 the_acl = old_secdesc->dacl;
5884                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5885                            printer, the_acl->num_aces));
5886
5887                 for (i = 0; i < the_acl->num_aces; i++) {
5888                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5889                                            &the_acl->aces[i].trustee),
5890                                   the_acl->aces[i].access_mask));
5891                 }
5892
5893                 the_acl = secdesc_ctr->sd->dacl;
5894
5895                 if (the_acl) {
5896                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5897                                    printer, the_acl->num_aces));
5898
5899                         for (i = 0; i < the_acl->num_aces; i++) {
5900                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5901                                                    &the_acl->aces[i].trustee),
5902                                            the_acl->aces[i].access_mask));
5903                         }
5904                 } else {
5905                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5906                 }
5907         }
5908
5909         new_secdesc = sec_desc_merge(p->mem_ctx, secdesc_ctr->sd, old_secdesc);
5910         if (new_secdesc == NULL) {
5911                 result = WERR_NOMEM;
5912                 goto done;
5913         }
5914
5915         if (security_descriptor_equal(new_secdesc, old_secdesc)) {
5916                 result = WERR_OK;
5917                 goto done;
5918         }
5919
5920         result = winreg_set_printer_secdesc(p->mem_ctx,
5921                                             get_server_info_system(),
5922                                             p->msg_ctx,
5923                                             printer,
5924                                             new_secdesc);
5925
5926  done:
5927         return result;
5928 }
5929
5930 /********************************************************************
5931  Canonicalize printer info from a client
5932  ********************************************************************/
5933
5934 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
5935                              struct spoolss_SetPrinterInfo2 *info2,
5936                              int snum)
5937 {
5938         fstring printername;
5939         const char *p;
5940
5941         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5942                 "portname=%s drivername=%s comment=%s location=%s\n",
5943                 info2->servername, info2->printername, info2->sharename,
5944                 info2->portname, info2->drivername, info2->comment,
5945                 info2->location));
5946
5947         /* we force some elements to "correct" values */
5948         info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
5949         if (info2->servername == NULL) {
5950                 return false;
5951         }
5952         info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
5953         if (info2->sharename == NULL) {
5954                 return false;
5955         }
5956
5957         /* check to see if we allow printername != sharename */
5958         if (lp_force_printername(snum)) {
5959                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
5960                                         global_myname(), info2->sharename);
5961         } else {
5962                 /* make sure printername is in \\server\printername format */
5963                 fstrcpy(printername, info2->printername);
5964                 p = printername;
5965                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
5966                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
5967                                 p++;
5968                 }
5969
5970                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
5971                                         global_myname(), p);
5972         }
5973         if (info2->printername == NULL) {
5974                 return false;
5975         }
5976
5977         info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
5978         info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
5979
5980         return true;
5981 }
5982
5983 /****************************************************************************
5984 ****************************************************************************/
5985
5986 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
5987 {
5988         char *cmd = lp_addport_cmd();
5989         char *command = NULL;
5990         int ret;
5991         bool is_print_op = false;
5992
5993         if ( !*cmd ) {
5994                 return WERR_ACCESS_DENIED;
5995         }
5996
5997         command = talloc_asprintf(ctx,
5998                         "%s \"%s\" \"%s\"", cmd, portname, uri );
5999         if (!command) {
6000                 return WERR_NOMEM;
6001         }
6002
6003         if ( token )
6004                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6005
6006         DEBUG(10,("Running [%s]\n", command));
6007
6008         /********* BEGIN SePrintOperatorPrivilege **********/
6009
6010         if ( is_print_op )
6011                 become_root();
6012
6013         ret = smbrun(command, NULL);
6014
6015         if ( is_print_op )
6016                 unbecome_root();
6017
6018         /********* END SePrintOperatorPrivilege **********/
6019
6020         DEBUGADD(10,("returned [%d]\n", ret));
6021
6022         TALLOC_FREE(command);
6023
6024         if ( ret != 0 ) {
6025                 return WERR_ACCESS_DENIED;
6026         }
6027
6028         return WERR_OK;
6029 }
6030
6031 /****************************************************************************
6032 ****************************************************************************/
6033
6034 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6035                              struct spoolss_SetPrinterInfo2 *info2,
6036                              const char *remote_machine,
6037                              struct messaging_context *msg_ctx)
6038 {
6039         char *cmd = lp_addprinter_cmd();
6040         char **qlines;
6041         char *command = NULL;
6042         int numlines;
6043         int ret;
6044         int fd;
6045         bool is_print_op = false;
6046
6047         if (!remote_machine) {
6048                 return false;
6049         }
6050
6051         command = talloc_asprintf(ctx,
6052                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6053                         cmd, info2->printername, info2->sharename,
6054                         info2->portname, info2->drivername,
6055                         info2->location, info2->comment, remote_machine);
6056         if (!command) {
6057                 return false;
6058         }
6059
6060         if ( token )
6061                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6062
6063         DEBUG(10,("Running [%s]\n", command));
6064
6065         /********* BEGIN SePrintOperatorPrivilege **********/
6066
6067         if ( is_print_op )
6068                 become_root();
6069
6070         if ( (ret = smbrun(command, &fd)) == 0 ) {
6071                 /* Tell everyone we updated smb.conf. */
6072                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6073         }
6074
6075         if ( is_print_op )
6076                 unbecome_root();
6077
6078         /********* END SePrintOperatorPrivilege **********/
6079
6080         DEBUGADD(10,("returned [%d]\n", ret));
6081
6082         TALLOC_FREE(command);
6083
6084         if ( ret != 0 ) {
6085                 if (fd != -1)
6086                         close(fd);
6087                 return false;
6088         }
6089
6090         /* reload our services immediately */
6091         become_root();
6092         reload_services(msg_ctx, -1, false);
6093         unbecome_root();
6094
6095         numlines = 0;
6096         /* Get lines and convert them back to dos-codepage */
6097         qlines = fd_lines_load(fd, &numlines, 0, NULL);
6098         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6099         close(fd);
6100
6101         /* Set the portname to what the script says the portname should be. */
6102         /* but don't require anything to be return from the script exit a good error code */
6103
6104         if (numlines) {
6105                 /* Set the portname to what the script says the portname should be. */
6106                 info2->portname = talloc_strdup(ctx, qlines[0]);
6107                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6108         }
6109
6110         TALLOC_FREE(qlines);
6111         return true;
6112 }
6113
6114 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6115                                const struct auth_serversupplied_info *server_info,
6116                                struct messaging_context *msg_ctx,
6117                                int snum,
6118                                struct spoolss_SetPrinterInfo2 *printer,
6119                                struct spoolss_PrinterInfo2 *old_printer)
6120 {
6121         bool force_update = (old_printer == NULL);
6122         const char *dnsdomname;
6123         const char *longname;
6124         const char *uncname;
6125         const char *spooling;
6126         DATA_BLOB buffer;
6127         WERROR result = WERR_OK;
6128
6129         if (force_update || !strequal(printer->drivername, old_printer->drivername)) {
6130                 push_reg_sz(mem_ctx, &buffer, printer->drivername);
6131                 winreg_set_printer_dataex(mem_ctx,
6132                                           server_info,
6133                                           msg_ctx,
6134                                           printer->sharename,
6135                                           SPOOL_DSSPOOLER_KEY,
6136                                           SPOOL_REG_DRIVERNAME,
6137                                           REG_SZ,
6138                                           buffer.data,
6139                                           buffer.length);
6140
6141                 if (!force_update) {
6142                         DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6143                                 printer->drivername));
6144
6145                         notify_printer_driver(server_event_context(), msg_ctx,
6146                                               snum, printer->drivername ?
6147                                               printer->drivername : "");
6148                 }
6149         }
6150
6151         if (force_update || !strequal(printer->comment, old_printer->comment)) {
6152                 push_reg_sz(mem_ctx, &buffer, printer->comment);
6153                 winreg_set_printer_dataex(mem_ctx,
6154                                           server_info,
6155                                           msg_ctx,
6156                                           printer->sharename,
6157                                           SPOOL_DSSPOOLER_KEY,
6158                                           SPOOL_REG_DESCRIPTION,
6159                                           REG_SZ,
6160                                           buffer.data,
6161                                           buffer.length);
6162
6163                 if (!force_update) {
6164                         notify_printer_comment(server_event_context(), msg_ctx,
6165                                                snum, printer->comment ?
6166                                                printer->comment : "");
6167                 }
6168         }
6169
6170         if (force_update || !strequal(printer->sharename, old_printer->sharename)) {
6171                 push_reg_sz(mem_ctx, &buffer, printer->sharename);
6172                 winreg_set_printer_dataex(mem_ctx,
6173                                           server_info,
6174                                           msg_ctx,
6175                                           printer->sharename,
6176                                           SPOOL_DSSPOOLER_KEY,
6177                                           SPOOL_REG_PRINTSHARENAME,
6178                                           REG_SZ,
6179                                           buffer.data,
6180                                           buffer.length);
6181
6182                 if (!force_update) {
6183                         notify_printer_sharename(server_event_context(),
6184                                                  msg_ctx,
6185                                                  snum, printer->sharename ?
6186                                                  printer->sharename : "");
6187                 }
6188         }
6189
6190         if (force_update || !strequal(printer->printername, old_printer->printername)) {
6191                 const char *p;
6192
6193                 p = strrchr(printer->printername, '\\' );
6194                 if (p != NULL) {
6195                         p++;
6196                 } else {
6197                         p = printer->printername;
6198                 }
6199
6200                 push_reg_sz(mem_ctx, &buffer, p);
6201                 winreg_set_printer_dataex(mem_ctx,
6202                                           server_info,
6203                                           msg_ctx,
6204                                           printer->sharename,
6205                                           SPOOL_DSSPOOLER_KEY,
6206                                           SPOOL_REG_PRINTERNAME,
6207                                           REG_SZ,
6208                                           buffer.data,
6209                                           buffer.length);
6210
6211                 if (!force_update) {
6212                         notify_printer_printername(server_event_context(),
6213                                                    msg_ctx, snum, p ? p : "");
6214                 }
6215         }
6216
6217         if (force_update || !strequal(printer->portname, old_printer->portname)) {
6218                 push_reg_sz(mem_ctx, &buffer, printer->portname);
6219                 winreg_set_printer_dataex(mem_ctx,
6220                                           server_info,
6221                                           msg_ctx,
6222                                           printer->sharename,
6223                                           SPOOL_DSSPOOLER_KEY,
6224                                           SPOOL_REG_PORTNAME,
6225                                           REG_SZ,
6226                                           buffer.data,
6227                                           buffer.length);
6228
6229                 if (!force_update) {
6230                         notify_printer_port(server_event_context(),
6231                                             msg_ctx, snum, printer->portname ?
6232                                             printer->portname : "");
6233                 }
6234         }
6235
6236         if (force_update || !strequal(printer->location, old_printer->location)) {
6237                 push_reg_sz(mem_ctx, &buffer, printer->location);
6238                 winreg_set_printer_dataex(mem_ctx,
6239                                           server_info,
6240                                           msg_ctx,
6241                                           printer->sharename,
6242                                           SPOOL_DSSPOOLER_KEY,
6243                                           SPOOL_REG_LOCATION,
6244                                           REG_SZ,
6245                                           buffer.data,
6246                                           buffer.length);
6247
6248                 if (!force_update) {
6249                         notify_printer_location(server_event_context(),
6250                                                 msg_ctx, snum,
6251                                                 printer->location ?
6252                                                 printer->location : "");
6253                 }
6254         }
6255
6256         if (force_update || !strequal(printer->sepfile, old_printer->sepfile)) {
6257                 push_reg_sz(mem_ctx, &buffer, printer->sepfile);
6258                 winreg_set_printer_dataex(mem_ctx,
6259                                           server_info,
6260                                           msg_ctx,
6261                                           printer->sharename,
6262                                           SPOOL_DSSPOOLER_KEY,
6263                                           SPOOL_REG_PRINTSEPARATORFILE,
6264                                           REG_SZ,
6265                                           buffer.data,
6266                                           buffer.length);
6267
6268                 if (!force_update) {
6269                         notify_printer_sepfile(server_event_context(),
6270                                                msg_ctx, snum,
6271                                                printer->sepfile ?
6272                                                printer->sepfile : "");
6273                 }
6274         }
6275
6276         if (force_update || printer->starttime != old_printer->starttime) {
6277                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6278                 SIVAL(buffer.data, 0, printer->starttime);
6279                 winreg_set_printer_dataex(mem_ctx,
6280                                           server_info,
6281                                           msg_ctx,
6282                                           printer->sharename,
6283                                           SPOOL_DSSPOOLER_KEY,
6284                                           SPOOL_REG_PRINTSTARTTIME,
6285                                           REG_DWORD,
6286                                           buffer.data,
6287                                           buffer.length);
6288         }
6289
6290         if (force_update || printer->untiltime != old_printer->untiltime) {
6291                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6292                 SIVAL(buffer.data, 0, printer->untiltime);
6293                 winreg_set_printer_dataex(mem_ctx,
6294                                           server_info,
6295                                           msg_ctx,
6296                                           printer->sharename,
6297                                           SPOOL_DSSPOOLER_KEY,
6298                                           SPOOL_REG_PRINTENDTIME,
6299                                           REG_DWORD,
6300                                           buffer.data,
6301                                           buffer.length);
6302         }
6303
6304         if (force_update || printer->priority != old_printer->priority) {
6305                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6306                 SIVAL(buffer.data, 0, printer->priority);
6307                 winreg_set_printer_dataex(mem_ctx,
6308                                           server_info,
6309                                           msg_ctx,
6310                                           printer->sharename,
6311                                           SPOOL_DSSPOOLER_KEY,
6312                                           SPOOL_REG_PRIORITY,
6313                                           REG_DWORD,
6314                                           buffer.data,
6315                                           buffer.length);
6316         }
6317
6318         if (force_update || printer->attributes != old_printer->attributes) {
6319                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6320                 SIVAL(buffer.data, 0, (printer->attributes &
6321                                        PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6322                 winreg_set_printer_dataex(mem_ctx,
6323                                           server_info,
6324                                           msg_ctx,
6325                                           printer->sharename,
6326                                           SPOOL_DSSPOOLER_KEY,
6327                                           SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6328                                           REG_DWORD,
6329                                           buffer.data,
6330                                           buffer.length);
6331
6332                 switch (printer->attributes & 0x3) {
6333                         case 0:
6334                                 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6335                                 break;
6336                         case 1:
6337                                 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6338                                 break;
6339                         case 2:
6340                                 spooling = SPOOL_REGVAL_PRINTDIRECT;
6341                                 break;
6342                         default:
6343                                 spooling = "unknown";
6344                 }
6345                 push_reg_sz(mem_ctx, &buffer, spooling);
6346                 winreg_set_printer_dataex(mem_ctx,
6347                                           server_info,
6348                                           msg_ctx,
6349                                           printer->sharename,
6350                                           SPOOL_DSSPOOLER_KEY,
6351                                           SPOOL_REG_PRINTSPOOLING,
6352                                           REG_SZ,
6353                                           buffer.data,
6354                                           buffer.length);
6355         }
6356
6357         push_reg_sz(mem_ctx, &buffer, global_myname());
6358         winreg_set_printer_dataex(mem_ctx,
6359                                   server_info,
6360                                   msg_ctx,
6361                                   printer->sharename,
6362                                   SPOOL_DSSPOOLER_KEY,
6363                                   SPOOL_REG_SHORTSERVERNAME,
6364                                   REG_SZ,
6365                                   buffer.data,
6366                                   buffer.length);
6367
6368         dnsdomname = get_mydnsfullname();
6369         if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6370                 longname = talloc_strdup(mem_ctx, dnsdomname);
6371         } else {
6372                 longname = talloc_strdup(mem_ctx, global_myname());
6373         }
6374         if (longname == NULL) {
6375                 result = WERR_NOMEM;
6376                 goto done;
6377         }
6378
6379         push_reg_sz(mem_ctx, &buffer, longname);
6380         winreg_set_printer_dataex(mem_ctx,
6381                                   server_info,
6382                                   msg_ctx,
6383                                   printer->sharename,
6384                                   SPOOL_DSSPOOLER_KEY,
6385                                   SPOOL_REG_SERVERNAME,
6386                                   REG_SZ,
6387                                   buffer.data,
6388                                   buffer.length);
6389
6390         uncname = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6391                                   global_myname(), printer->sharename);
6392         push_reg_sz(mem_ctx, &buffer, uncname);
6393         winreg_set_printer_dataex(mem_ctx,
6394                                   server_info,
6395                                   msg_ctx,
6396                                   printer->sharename,
6397                                   SPOOL_DSSPOOLER_KEY,
6398                                   SPOOL_REG_UNCNAME,
6399                                   REG_SZ,
6400                                   buffer.data,
6401                                   buffer.length);
6402
6403 done:
6404         return result;
6405 }
6406
6407 /********************************************************************
6408  * Called by spoolss_api_setprinter
6409  * when updating a printer description.
6410  ********************************************************************/
6411
6412 static WERROR update_printer(struct pipes_struct *p,
6413                              struct policy_handle *handle,
6414                              struct spoolss_SetPrinterInfoCtr *info_ctr,
6415                              struct spoolss_DeviceMode *devmode)
6416 {
6417         uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6418         struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6419         struct spoolss_PrinterInfo2 *old_printer;
6420         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6421         int snum;
6422         WERROR result = WERR_OK;
6423         TALLOC_CTX *tmp_ctx;
6424
6425         DEBUG(8,("update_printer\n"));
6426
6427         tmp_ctx = talloc_new(p->mem_ctx);
6428         if (tmp_ctx == NULL) {
6429                 return WERR_NOMEM;
6430         }
6431
6432         if (!Printer) {
6433                 result = WERR_BADFID;
6434                 goto done;
6435         }
6436
6437         if (!get_printer_snum(p, handle, &snum, NULL)) {
6438                 result = WERR_BADFID;
6439                 goto done;
6440         }
6441
6442         result = winreg_get_printer(tmp_ctx,
6443                                     get_server_info_system(),
6444                                     p->msg_ctx,
6445                                     lp_const_servicename(snum),
6446                                     &old_printer);
6447         if (!W_ERROR_IS_OK(result)) {
6448                 result = WERR_BADFID;
6449                 goto done;
6450         }
6451
6452         /* Do sanity check on the requested changes for Samba */
6453         if (!check_printer_ok(tmp_ctx, printer, snum)) {
6454                 result = WERR_INVALID_PARAM;
6455                 goto done;
6456         }
6457
6458         /* FIXME!!! If the driver has changed we really should verify that
6459            it is installed before doing much else   --jerry */
6460
6461         /* Check calling user has permission to update printer description */
6462         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6463                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6464                 result = WERR_ACCESS_DENIED;
6465                 goto done;
6466         }
6467
6468         /* Call addprinter hook */
6469         /* Check changes to see if this is really needed */
6470
6471         if (*lp_addprinter_cmd() &&
6472                         (!strequal(printer->drivername, old_printer->drivername) ||
6473                          !strequal(printer->comment, old_printer->comment) ||
6474                          !strequal(printer->portname, old_printer->portname) ||
6475                          !strequal(printer->location, old_printer->location)) )
6476         {
6477                 /* add_printer_hook() will call reload_services() */
6478                 if (!add_printer_hook(tmp_ctx, p->server_info->ptok,
6479                                       printer, p->client_id->addr,
6480                                       p->msg_ctx)) {
6481                         result = WERR_ACCESS_DENIED;
6482                         goto done;
6483                 }
6484         }
6485
6486         update_dsspooler(tmp_ctx,
6487                          get_server_info_system(),
6488                          p->msg_ctx,
6489                          snum,
6490                          printer,
6491                          old_printer);
6492
6493         printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6494
6495         if (devmode == NULL) {
6496                 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6497         }
6498         result = winreg_update_printer(tmp_ctx,
6499                                        get_server_info_system(),
6500                                        p->msg_ctx,
6501                                        printer->sharename,
6502                                        printer_mask,
6503                                        printer,
6504                                        devmode,
6505                                        NULL);
6506
6507 done:
6508         talloc_free(tmp_ctx);
6509
6510         return result;
6511 }
6512
6513 /****************************************************************************
6514 ****************************************************************************/
6515 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6516                                            struct policy_handle *handle,
6517                                            struct spoolss_SetPrinterInfo7 *info7)
6518 {
6519 #ifdef HAVE_ADS
6520         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6521         WERROR result;
6522         int snum;
6523         struct printer_handle *Printer;
6524
6525         if ( lp_security() != SEC_ADS ) {
6526                 return WERR_UNKNOWN_LEVEL;
6527         }
6528
6529         Printer = find_printer_index_by_hnd(p, handle);
6530
6531         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6532
6533         if (!Printer)
6534                 return WERR_BADFID;
6535
6536         if (!get_printer_snum(p, handle, &snum, NULL))
6537                 return WERR_BADFID;
6538
6539         result = winreg_get_printer(p->mem_ctx,
6540                                     get_server_info_system(),
6541                                     p->msg_ctx,
6542                                     lp_servicename(snum),
6543                                     &pinfo2);
6544         if (!W_ERROR_IS_OK(result)) {
6545                 return WERR_BADFID;
6546         }
6547
6548         nt_printer_publish(pinfo2,
6549                            get_server_info_system(),
6550                            p->msg_ctx,
6551                            pinfo2,
6552                            info7->action);
6553
6554         TALLOC_FREE(pinfo2);
6555         return WERR_OK;
6556 #else
6557         return WERR_UNKNOWN_LEVEL;
6558 #endif
6559 }
6560
6561 /********************************************************************
6562  ********************************************************************/
6563
6564 static WERROR update_printer_devmode(struct pipes_struct *p,
6565                                      struct policy_handle *handle,
6566                                      struct spoolss_DeviceMode *devmode)
6567 {
6568         int snum;
6569         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6570         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6571
6572         DEBUG(8,("update_printer_devmode\n"));
6573
6574         if (!Printer) {
6575                 return WERR_BADFID;
6576         }
6577
6578         if (!get_printer_snum(p, handle, &snum, NULL)) {
6579                 return WERR_BADFID;
6580         }
6581
6582         /* Check calling user has permission to update printer description */
6583         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6584                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6585                 return WERR_ACCESS_DENIED;
6586         }
6587
6588         return winreg_update_printer(p->mem_ctx,
6589                                      get_server_info_system(),
6590                                      p->msg_ctx,
6591                                      lp_const_servicename(snum),
6592                                      info2_mask,
6593                                      NULL,
6594                                      devmode,
6595                                      NULL);
6596 }
6597
6598
6599 /****************************************************************
6600  _spoolss_SetPrinter
6601 ****************************************************************/
6602
6603 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6604                            struct spoolss_SetPrinter *r)
6605 {
6606         WERROR result;
6607
6608         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6609
6610         if (!Printer) {
6611                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6612                         OUR_HANDLE(r->in.handle)));
6613                 return WERR_BADFID;
6614         }
6615
6616         /* check the level */
6617         switch (r->in.info_ctr->level) {
6618                 case 0:
6619                         return control_printer(r->in.handle, r->in.command, p);
6620                 case 2:
6621                         result = update_printer(p, r->in.handle,
6622                                                 r->in.info_ctr,
6623                                                 r->in.devmode_ctr->devmode);
6624                         if (!W_ERROR_IS_OK(result))
6625                                 return result;
6626                         if (r->in.secdesc_ctr->sd)
6627                                 result = update_printer_sec(r->in.handle, p,
6628                                                             r->in.secdesc_ctr);
6629                         return result;
6630                 case 3:
6631                         return update_printer_sec(r->in.handle, p,
6632                                                   r->in.secdesc_ctr);
6633                 case 7:
6634                         return publish_or_unpublish_printer(p, r->in.handle,
6635                                                             r->in.info_ctr->info.info7);
6636                 case 8:
6637                         return update_printer_devmode(p, r->in.handle,
6638                                                       r->in.devmode_ctr->devmode);
6639                 default:
6640                         return WERR_UNKNOWN_LEVEL;
6641         }
6642 }
6643
6644 /****************************************************************
6645  _spoolss_FindClosePrinterNotify
6646 ****************************************************************/
6647
6648 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
6649                                        struct spoolss_FindClosePrinterNotify *r)
6650 {
6651         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6652
6653         if (!Printer) {
6654                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6655                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6656                 return WERR_BADFID;
6657         }
6658
6659         if (Printer->notify.cli_chan != NULL &&
6660             Printer->notify.cli_chan->active_connections > 0) {
6661                 int snum = -1;
6662
6663                 if (Printer->printer_type == SPLHND_PRINTER) {
6664                         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6665                                 return WERR_BADFID;
6666                         }
6667                 }
6668
6669                 srv_spoolss_replycloseprinter(snum, Printer);
6670         }
6671
6672         Printer->notify.flags=0;
6673         Printer->notify.options=0;
6674         Printer->notify.localmachine[0]='\0';
6675         Printer->notify.printerlocal=0;
6676         TALLOC_FREE(Printer->notify.option);
6677
6678         return WERR_OK;
6679 }
6680
6681 /****************************************************************
6682  _spoolss_AddJob
6683 ****************************************************************/
6684
6685 WERROR _spoolss_AddJob(struct pipes_struct *p,
6686                        struct spoolss_AddJob *r)
6687 {
6688         if (!r->in.buffer && (r->in.offered != 0)) {
6689                 return WERR_INVALID_PARAM;
6690         }
6691
6692         /* this is what a NT server returns for AddJob. AddJob must fail on
6693          * non-local printers */
6694
6695         if (r->in.level != 1) {
6696                 return WERR_UNKNOWN_LEVEL;
6697         }
6698
6699         return WERR_INVALID_PARAM;
6700 }
6701
6702 /****************************************************************************
6703 fill_job_info1
6704 ****************************************************************************/
6705
6706 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6707                              struct spoolss_JobInfo1 *r,
6708                              const print_queue_struct *queue,
6709                              int position, int snum,
6710                              struct spoolss_PrinterInfo2 *pinfo2)
6711 {
6712         struct tm *t;
6713
6714         t = gmtime(&queue->time);
6715
6716         r->job_id               = queue->job;
6717
6718         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6719         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6720         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
6721         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6722         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6723         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6724         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6725         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6726         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6727         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6728         r->text_status          = talloc_strdup(mem_ctx, "");
6729         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6730
6731         r->status               = nt_printj_status(queue->status);
6732         r->priority             = queue->priority;
6733         r->position             = position;
6734         r->total_pages          = queue->page_count;
6735         r->pages_printed        = 0; /* ??? */
6736
6737         init_systemtime(&r->submitted, t);
6738
6739         return WERR_OK;
6740 }
6741
6742 /****************************************************************************
6743 fill_job_info2
6744 ****************************************************************************/
6745
6746 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6747                              struct spoolss_JobInfo2 *r,
6748                              const print_queue_struct *queue,
6749                              int position, int snum,
6750                              struct spoolss_PrinterInfo2 *pinfo2,
6751                              struct spoolss_DeviceMode *devmode)
6752 {
6753         struct tm *t;
6754
6755         t = gmtime(&queue->time);
6756
6757         r->job_id               = queue->job;
6758
6759         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6760         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6761         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
6762         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6763         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6764         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6765         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6766         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6767         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
6768         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6769         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6770         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6771         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
6772         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6773         r->parameters           = talloc_strdup(mem_ctx, "");
6774         W_ERROR_HAVE_NO_MEMORY(r->parameters);
6775         r->driver_name          = talloc_strdup(mem_ctx, pinfo2->drivername);
6776         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6777
6778         r->devmode              = devmode;
6779
6780         r->text_status          = talloc_strdup(mem_ctx, "");
6781         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6782
6783         r->secdesc              = NULL;
6784
6785         r->status               = nt_printj_status(queue->status);
6786         r->priority             = queue->priority;
6787         r->position             = position;
6788         r->start_time           = 0;
6789         r->until_time           = 0;
6790         r->total_pages          = queue->page_count;
6791         r->size                 = queue->size;
6792         init_systemtime(&r->submitted, t);
6793         r->time                 = 0;
6794         r->pages_printed        = 0; /* ??? */
6795
6796         return WERR_OK;
6797 }
6798
6799 /****************************************************************************
6800 fill_job_info3
6801 ****************************************************************************/
6802
6803 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6804                              struct spoolss_JobInfo3 *r,
6805                              const print_queue_struct *queue,
6806                              const print_queue_struct *next_queue,
6807                              int position, int snum,
6808                              struct spoolss_PrinterInfo2 *pinfo2)
6809 {
6810         r->job_id               = queue->job;
6811         r->next_job_id          = 0;
6812         if (next_queue) {
6813                 r->next_job_id  = next_queue->job;
6814         }
6815         r->reserved             = 0;
6816
6817         return WERR_OK;
6818 }
6819
6820 /****************************************************************************
6821  Enumjobs at level 1.
6822 ****************************************************************************/
6823
6824 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6825                               const print_queue_struct *queue,
6826                               uint32_t num_queues, int snum,
6827                               struct spoolss_PrinterInfo2 *pinfo2,
6828                               union spoolss_JobInfo **info_p,
6829                               uint32_t *count)
6830 {
6831         union spoolss_JobInfo *info;
6832         int i;
6833         WERROR result = WERR_OK;
6834
6835         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6836         W_ERROR_HAVE_NO_MEMORY(info);
6837
6838         *count = num_queues;
6839
6840         for (i=0; i<*count; i++) {
6841                 result = fill_job_info1(info,
6842                                         &info[i].info1,
6843                                         &queue[i],
6844                                         i,
6845                                         snum,
6846                                         pinfo2);
6847                 if (!W_ERROR_IS_OK(result)) {
6848                         goto out;
6849                 }
6850         }
6851
6852  out:
6853         if (!W_ERROR_IS_OK(result)) {
6854                 TALLOC_FREE(info);
6855                 *count = 0;
6856                 return result;
6857         }
6858
6859         *info_p = info;
6860
6861         return WERR_OK;
6862 }
6863
6864 /****************************************************************************
6865  Enumjobs at level 2.
6866 ****************************************************************************/
6867
6868 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6869                               const print_queue_struct *queue,
6870                               uint32_t num_queues, int snum,
6871                               struct spoolss_PrinterInfo2 *pinfo2,
6872                               union spoolss_JobInfo **info_p,
6873                               uint32_t *count)
6874 {
6875         union spoolss_JobInfo *info;
6876         int i;
6877         WERROR result = WERR_OK;
6878
6879         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6880         W_ERROR_HAVE_NO_MEMORY(info);
6881
6882         *count = num_queues;
6883
6884         for (i=0; i<*count; i++) {
6885                 struct spoolss_DeviceMode *devmode;
6886
6887                 result = spoolss_create_default_devmode(info,
6888                                                         pinfo2->printername,
6889                                                         &devmode);
6890                 if (!W_ERROR_IS_OK(result)) {
6891                         DEBUG(3, ("Can't proceed w/o a devmode!"));
6892                         goto out;
6893                 }
6894
6895                 result = fill_job_info2(info,
6896                                         &info[i].info2,
6897                                         &queue[i],
6898                                         i,
6899                                         snum,
6900                                         pinfo2,
6901                                         devmode);
6902                 if (!W_ERROR_IS_OK(result)) {
6903                         goto out;
6904                 }
6905         }
6906
6907  out:
6908         if (!W_ERROR_IS_OK(result)) {
6909                 TALLOC_FREE(info);
6910                 *count = 0;
6911                 return result;
6912         }
6913
6914         *info_p = info;
6915
6916         return WERR_OK;
6917 }
6918
6919 /****************************************************************************
6920  Enumjobs at level 3.
6921 ****************************************************************************/
6922
6923 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
6924                               const print_queue_struct *queue,
6925                               uint32_t num_queues, int snum,
6926                               struct spoolss_PrinterInfo2 *pinfo2,
6927                               union spoolss_JobInfo **info_p,
6928                               uint32_t *count)
6929 {
6930         union spoolss_JobInfo *info;
6931         int i;
6932         WERROR result = WERR_OK;
6933
6934         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6935         W_ERROR_HAVE_NO_MEMORY(info);
6936
6937         *count = num_queues;
6938
6939         for (i=0; i<*count; i++) {
6940                 const print_queue_struct *next_queue = NULL;
6941
6942                 if (i+1 < *count) {
6943                         next_queue = &queue[i+1];
6944                 }
6945
6946                 result = fill_job_info3(info,
6947                                         &info[i].info3,
6948                                         &queue[i],
6949                                         next_queue,
6950                                         i,
6951                                         snum,
6952                                         pinfo2);
6953                 if (!W_ERROR_IS_OK(result)) {
6954                         goto out;
6955                 }
6956         }
6957
6958  out:
6959         if (!W_ERROR_IS_OK(result)) {
6960                 TALLOC_FREE(info);
6961                 *count = 0;
6962                 return result;
6963         }
6964
6965         *info_p = info;
6966
6967         return WERR_OK;
6968 }
6969
6970 /****************************************************************
6971  _spoolss_EnumJobs
6972 ****************************************************************/
6973
6974 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
6975                          struct spoolss_EnumJobs *r)
6976 {
6977         WERROR result;
6978         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6979         int snum;
6980         print_status_struct prt_status;
6981         print_queue_struct *queue = NULL;
6982         uint32_t count;
6983
6984         /* that's an [in out] buffer */
6985
6986         if (!r->in.buffer && (r->in.offered != 0)) {
6987                 return WERR_INVALID_PARAM;
6988         }
6989
6990         DEBUG(4,("_spoolss_EnumJobs\n"));
6991
6992         *r->out.needed = 0;
6993         *r->out.count = 0;
6994         *r->out.info = NULL;
6995
6996         /* lookup the printer snum and tdb entry */
6997
6998         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6999                 return WERR_BADFID;
7000         }
7001
7002         result = winreg_get_printer(p->mem_ctx,
7003                                     get_server_info_system(),
7004                                     p->msg_ctx,
7005                                     lp_const_servicename(snum),
7006                                     &pinfo2);
7007         if (!W_ERROR_IS_OK(result)) {
7008                 return result;
7009         }
7010
7011         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7012         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7013                 count, prt_status.status, prt_status.message));
7014
7015         if (count == 0) {
7016                 SAFE_FREE(queue);
7017                 TALLOC_FREE(pinfo2);
7018                 return WERR_OK;
7019         }
7020
7021         switch (r->in.level) {
7022         case 1:
7023                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7024                                          pinfo2, r->out.info, r->out.count);
7025                 break;
7026         case 2:
7027                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7028                                          pinfo2, r->out.info, r->out.count);
7029                 break;
7030         case 3:
7031                 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7032                                          pinfo2, r->out.info, r->out.count);
7033                 break;
7034         default:
7035                 result = WERR_UNKNOWN_LEVEL;
7036                 break;
7037         }
7038
7039         SAFE_FREE(queue);
7040         TALLOC_FREE(pinfo2);
7041
7042         if (!W_ERROR_IS_OK(result)) {
7043                 return result;
7044         }
7045
7046         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7047                                                      spoolss_EnumJobs, 
7048                                                      *r->out.info, r->in.level,
7049                                                      *r->out.count);
7050         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7051         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7052
7053         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7054 }
7055
7056 /****************************************************************
7057  _spoolss_ScheduleJob
7058 ****************************************************************/
7059
7060 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7061                             struct spoolss_ScheduleJob *r)
7062 {
7063         return WERR_OK;
7064 }
7065
7066 /****************************************************************
7067 ****************************************************************/
7068
7069 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7070                                struct messaging_context *msg_ctx,
7071                                const char *printer_name,
7072                                uint32_t job_id,
7073                                struct spoolss_SetJobInfo1 *r)
7074 {
7075         char *old_doc_name;
7076
7077         if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7078                 return WERR_BADFID;
7079         }
7080
7081         if (strequal(old_doc_name, r->document_name)) {
7082                 return WERR_OK;
7083         }
7084
7085         if (!print_job_set_name(server_event_context(), msg_ctx,
7086                                 printer_name, job_id, r->document_name)) {
7087                 return WERR_BADFID;
7088         }
7089
7090         return WERR_OK;
7091 }
7092
7093 /****************************************************************
7094  _spoolss_SetJob
7095 ****************************************************************/
7096
7097 WERROR _spoolss_SetJob(struct pipes_struct *p,
7098                        struct spoolss_SetJob *r)
7099 {
7100         const struct auth_serversupplied_info *server_info = p->server_info;
7101         int snum;
7102         WERROR errcode = WERR_BADFUNC;
7103
7104         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7105                 return WERR_BADFID;
7106         }
7107
7108         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7109                 return WERR_INVALID_PRINTER_NAME;
7110         }
7111
7112         switch (r->in.command) {
7113         case SPOOLSS_JOB_CONTROL_CANCEL:
7114         case SPOOLSS_JOB_CONTROL_DELETE:
7115                 errcode = print_job_delete(server_info, p->msg_ctx,
7116                                            snum, r->in.job_id);
7117                 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7118                         errcode = WERR_OK;
7119                 }
7120                 break;
7121         case SPOOLSS_JOB_CONTROL_PAUSE:
7122                 if (print_job_pause(server_info, p->msg_ctx,
7123                                     snum, r->in.job_id, &errcode)) {
7124                         errcode = WERR_OK;
7125                 }
7126                 break;
7127         case SPOOLSS_JOB_CONTROL_RESTART:
7128         case SPOOLSS_JOB_CONTROL_RESUME:
7129                 if (print_job_resume(server_info, p->msg_ctx,
7130                                      snum, r->in.job_id, &errcode)) {
7131                         errcode = WERR_OK;
7132                 }
7133                 break;
7134         case 0:
7135                 errcode = WERR_OK;
7136                 break;
7137         default:
7138                 return WERR_UNKNOWN_LEVEL;
7139         }
7140
7141         if (!W_ERROR_IS_OK(errcode)) {
7142                 return errcode;
7143         }
7144
7145         if (r->in.ctr == NULL) {
7146                 return errcode;
7147         }
7148
7149         switch (r->in.ctr->level) {
7150         case 1:
7151                 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7152                                            lp_const_servicename(snum),
7153                                            r->in.job_id,
7154                                            r->in.ctr->info.info1);
7155                 break;
7156         case 2:
7157         case 3:
7158         case 4:
7159         default:
7160                 return WERR_UNKNOWN_LEVEL;
7161         }
7162
7163         return errcode;
7164 }
7165
7166 /****************************************************************************
7167  Enumerates all printer drivers by level and architecture.
7168 ****************************************************************************/
7169
7170 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7171                                                        const struct auth_serversupplied_info *server_info,
7172                                                        struct messaging_context *msg_ctx,
7173                                                        const char *servername,
7174                                                        const char *architecture,
7175                                                        uint32_t level,
7176                                                        union spoolss_DriverInfo **info_p,
7177                                                        uint32_t *count_p)
7178 {
7179         int i;
7180         uint32_t version;
7181         struct spoolss_DriverInfo8 *driver;
7182         union spoolss_DriverInfo *info = NULL;
7183         uint32_t count = 0;
7184         WERROR result = WERR_OK;
7185         uint32_t num_drivers;
7186         const char **drivers;
7187
7188         *count_p = 0;
7189         *info_p = NULL;
7190
7191         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7192                 result = winreg_get_driver_list(mem_ctx, server_info, msg_ctx,
7193                                                 architecture, version,
7194                                                 &num_drivers, &drivers);
7195                 if (!W_ERROR_IS_OK(result)) {
7196                         goto out;
7197                 }
7198                 DEBUG(4, ("we have:[%d] drivers in environment"
7199                           " [%s] and version [%d]\n",
7200                           num_drivers, architecture, version));
7201
7202                 if (num_drivers != 0) {
7203                         info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
7204                                                     union spoolss_DriverInfo,
7205                                                     count + num_drivers);
7206                         if (!info) {
7207                                 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7208                                         "failed to enlarge driver info buffer!\n"));
7209                                 result = WERR_NOMEM;
7210                                 goto out;
7211                         }
7212                 }
7213
7214                 for (i = 0; i < num_drivers; i++) {
7215                         DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7216
7217                         result = winreg_get_driver(mem_ctx, server_info,
7218                                                    msg_ctx,
7219                                                    architecture, drivers[i],
7220                                                    version, &driver);
7221                         if (!W_ERROR_IS_OK(result)) {
7222                                 goto out;
7223                         }
7224
7225                         switch (level) {
7226                         case 1:
7227                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
7228                                                                    driver, servername);
7229                                 break;
7230                         case 2:
7231                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
7232                                                                    driver, servername);
7233                                 break;
7234                         case 3:
7235                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
7236                                                                    driver, servername);
7237                                 break;
7238                         case 4:
7239                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
7240                                                                    driver, servername);
7241                                 break;
7242                         case 5:
7243                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
7244                                                                    driver, servername);
7245                                 break;
7246                         case 6:
7247                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
7248                                                                    driver, servername);
7249                                 break;
7250                         case 8:
7251                                 result = fill_printer_driver_info8(info, &info[count+i].info8,
7252                                                                    driver, servername);
7253                                 break;
7254                         default:
7255                                 result = WERR_UNKNOWN_LEVEL;
7256                                 break;
7257                         }
7258
7259                         TALLOC_FREE(driver);
7260
7261                         if (!W_ERROR_IS_OK(result)) {
7262                                 goto out;
7263                         }
7264                 }
7265
7266                 count += num_drivers;
7267                 TALLOC_FREE(drivers);
7268         }
7269
7270  out:
7271         TALLOC_FREE(drivers);
7272
7273         if (!W_ERROR_IS_OK(result)) {
7274                 TALLOC_FREE(info);
7275                 return result;
7276         }
7277
7278         *info_p = info;
7279         *count_p = count;
7280
7281         return WERR_OK;
7282 }
7283
7284 /****************************************************************************
7285  Enumerates all printer drivers by level.
7286 ****************************************************************************/
7287
7288 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7289                                        const struct auth_serversupplied_info *server_info,
7290                                        struct messaging_context *msg_ctx,
7291                                        const char *servername,
7292                                        const char *architecture,
7293                                        uint32_t level,
7294                                        union spoolss_DriverInfo **info_p,
7295                                        uint32_t *count_p)
7296 {
7297         uint32_t a,i;
7298         WERROR result = WERR_OK;
7299
7300         if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7301
7302                 for (a=0; archi_table[a].long_archi != NULL; a++) {
7303
7304                         union spoolss_DriverInfo *info = NULL;
7305                         uint32_t count = 0;
7306
7307                         result = enumprinterdrivers_level_by_architecture(mem_ctx,
7308                                                                           server_info,
7309                                                                           msg_ctx,
7310                                                                           servername,
7311                                                                           archi_table[a].long_archi,
7312                                                                           level,
7313                                                                           &info,
7314                                                                           &count);
7315                         if (!W_ERROR_IS_OK(result)) {
7316                                 continue;
7317                         }
7318
7319                         for (i=0; i < count; i++) {
7320                                 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7321                                              info[i], info_p, count_p);
7322                         }
7323                 }
7324
7325                 return result;
7326         }
7327
7328         return enumprinterdrivers_level_by_architecture(mem_ctx,
7329                                                         server_info,
7330                                                         msg_ctx,
7331                                                         servername,
7332                                                         architecture,
7333                                                         level,
7334                                                         info_p,
7335                                                         count_p);
7336 }
7337
7338 /****************************************************************
7339  _spoolss_EnumPrinterDrivers
7340 ****************************************************************/
7341
7342 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7343                                    struct spoolss_EnumPrinterDrivers *r)
7344 {
7345         const char *cservername;
7346         WERROR result;
7347
7348         /* that's an [in out] buffer */
7349
7350         if (!r->in.buffer && (r->in.offered != 0)) {
7351                 return WERR_INVALID_PARAM;
7352         }
7353
7354         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7355
7356         *r->out.needed = 0;
7357         *r->out.count = 0;
7358         *r->out.info = NULL;
7359
7360         cservername = canon_servername(r->in.server);
7361
7362         if (!is_myname_or_ipaddr(cservername)) {
7363                 return WERR_UNKNOWN_PRINTER_DRIVER;
7364         }
7365
7366         result = enumprinterdrivers_level(p->mem_ctx,
7367                                           get_server_info_system(),
7368                                           p->msg_ctx,
7369                                           cservername,
7370                                           r->in.environment,
7371                                           r->in.level,
7372                                           r->out.info,
7373                                           r->out.count);
7374         if (!W_ERROR_IS_OK(result)) {
7375                 return result;
7376         }
7377
7378         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7379                                                      spoolss_EnumPrinterDrivers, 
7380                                                      *r->out.info, r->in.level,
7381                                                      *r->out.count);
7382         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7383         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7384
7385         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7386 }
7387
7388 /****************************************************************
7389  _spoolss_EnumForms
7390 ****************************************************************/
7391
7392 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7393                           struct spoolss_EnumForms *r)
7394 {
7395         WERROR result;
7396
7397         *r->out.count = 0;
7398         *r->out.needed = 0;
7399         *r->out.info = NULL;
7400
7401         /* that's an [in out] buffer */
7402
7403         if (!r->in.buffer && (r->in.offered != 0) ) {
7404                 return WERR_INVALID_PARAM;
7405         }
7406
7407         DEBUG(4,("_spoolss_EnumForms\n"));
7408         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7409         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7410
7411         switch (r->in.level) {
7412         case 1:
7413                 result = winreg_printer_enumforms1(p->mem_ctx,
7414                                                    get_server_info_system(),
7415                                                    p->msg_ctx,
7416                                                    r->out.count,
7417                                                    r->out.info);
7418                 break;
7419         default:
7420                 result = WERR_UNKNOWN_LEVEL;
7421                 break;
7422         }
7423
7424         if (!W_ERROR_IS_OK(result)) {
7425                 return result;
7426         }
7427
7428         if (*r->out.count == 0) {
7429                 return WERR_NO_MORE_ITEMS;
7430         }
7431
7432         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7433                                                      spoolss_EnumForms, 
7434                                                      *r->out.info, r->in.level,
7435                                                      *r->out.count);
7436         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7437         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7438
7439         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7440 }
7441
7442 /****************************************************************
7443  _spoolss_GetForm
7444 ****************************************************************/
7445
7446 WERROR _spoolss_GetForm(struct pipes_struct *p,
7447                         struct spoolss_GetForm *r)
7448 {
7449         WERROR result;
7450
7451         /* that's an [in out] buffer */
7452
7453         if (!r->in.buffer && (r->in.offered != 0)) {
7454                 return WERR_INVALID_PARAM;
7455         }
7456
7457         DEBUG(4,("_spoolss_GetForm\n"));
7458         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7459         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7460
7461         switch (r->in.level) {
7462         case 1:
7463                 result = winreg_printer_getform1(p->mem_ctx,
7464                                                  get_server_info_system(),
7465                                                  p->msg_ctx,
7466                                                  r->in.form_name,
7467                                                  &r->out.info->info1);
7468                 break;
7469         default:
7470                 result = WERR_UNKNOWN_LEVEL;
7471                 break;
7472         }
7473
7474         if (!W_ERROR_IS_OK(result)) {
7475                 TALLOC_FREE(r->out.info);
7476                 return result;
7477         }
7478
7479         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo, 
7480                                                r->out.info, r->in.level);
7481         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7482
7483         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7484 }
7485
7486 /****************************************************************************
7487 ****************************************************************************/
7488
7489 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7490                           struct spoolss_PortInfo1 *r,
7491                           const char *name)
7492 {
7493         r->port_name = talloc_strdup(mem_ctx, name);
7494         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7495
7496         return WERR_OK;
7497 }
7498
7499 /****************************************************************************
7500  TODO: This probably needs distinguish between TCP/IP and Local ports
7501  somehow.
7502 ****************************************************************************/
7503
7504 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7505                           struct spoolss_PortInfo2 *r,
7506                           const char *name)
7507 {
7508         r->port_name = talloc_strdup(mem_ctx, name);
7509         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7510
7511         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7512         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7513
7514         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7515         W_ERROR_HAVE_NO_MEMORY(r->description);
7516
7517         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7518         r->reserved = 0;
7519
7520         return WERR_OK;
7521 }
7522
7523
7524 /****************************************************************************
7525  wrapper around the enumer ports command
7526 ****************************************************************************/
7527
7528 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7529 {
7530         char *cmd = lp_enumports_cmd();
7531         char **qlines = NULL;
7532         char *command = NULL;
7533         int numlines;
7534         int ret;
7535         int fd;
7536
7537         *count = 0;
7538         *lines = NULL;
7539
7540         /* if no hook then just fill in the default port */
7541
7542         if ( !*cmd ) {
7543                 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7544                         return WERR_NOMEM;
7545                 }
7546                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7547                         TALLOC_FREE(qlines);
7548                         return WERR_NOMEM;
7549                 }
7550                 qlines[1] = NULL;
7551                 numlines = 1;
7552         }
7553         else {
7554                 /* we have a valid enumport command */
7555
7556                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7557                 if (!command) {
7558                         return WERR_NOMEM;
7559                 }
7560
7561                 DEBUG(10,("Running [%s]\n", command));
7562                 ret = smbrun(command, &fd);
7563                 DEBUG(10,("Returned [%d]\n", ret));
7564                 TALLOC_FREE(command);
7565                 if (ret != 0) {
7566                         if (fd != -1) {
7567                                 close(fd);
7568                         }
7569                         return WERR_ACCESS_DENIED;
7570                 }
7571
7572                 numlines = 0;
7573                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7574                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7575                 close(fd);
7576         }
7577
7578         *count = numlines;
7579         *lines = qlines;
7580
7581         return WERR_OK;
7582 }
7583
7584 /****************************************************************************
7585  enumports level 1.
7586 ****************************************************************************/
7587
7588 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7589                                 union spoolss_PortInfo **info_p,
7590                                 uint32_t *count)
7591 {
7592         union spoolss_PortInfo *info = NULL;
7593         int i=0;
7594         WERROR result = WERR_OK;
7595         char **qlines = NULL;
7596         int numlines = 0;
7597
7598         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7599         if (!W_ERROR_IS_OK(result)) {
7600                 goto out;
7601         }
7602
7603         if (numlines) {
7604                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7605                 if (!info) {
7606                         DEBUG(10,("Returning WERR_NOMEM\n"));
7607                         result = WERR_NOMEM;
7608                         goto out;
7609                 }
7610
7611                 for (i=0; i<numlines; i++) {
7612                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7613                         result = fill_port_1(info, &info[i].info1, qlines[i]);
7614                         if (!W_ERROR_IS_OK(result)) {
7615                                 goto out;
7616                         }
7617                 }
7618         }
7619         TALLOC_FREE(qlines);
7620
7621 out:
7622         if (!W_ERROR_IS_OK(result)) {
7623                 TALLOC_FREE(info);
7624                 TALLOC_FREE(qlines);
7625                 *count = 0;
7626                 *info_p = NULL;
7627                 return result;
7628         }
7629
7630         *info_p = info;
7631         *count = numlines;
7632
7633         return WERR_OK;
7634 }
7635
7636 /****************************************************************************
7637  enumports level 2.
7638 ****************************************************************************/
7639
7640 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7641                                 union spoolss_PortInfo **info_p,
7642                                 uint32_t *count)
7643 {
7644         union spoolss_PortInfo *info = NULL;
7645         int i=0;
7646         WERROR result = WERR_OK;
7647         char **qlines = NULL;
7648         int numlines = 0;
7649
7650         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7651         if (!W_ERROR_IS_OK(result)) {
7652                 goto out;
7653         }
7654
7655         if (numlines) {
7656                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7657                 if (!info) {
7658                         DEBUG(10,("Returning WERR_NOMEM\n"));
7659                         result = WERR_NOMEM;
7660                         goto out;
7661                 }
7662
7663                 for (i=0; i<numlines; i++) {
7664                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7665                         result = fill_port_2(info, &info[i].info2, qlines[i]);
7666                         if (!W_ERROR_IS_OK(result)) {
7667                                 goto out;
7668                         }
7669                 }
7670         }
7671         TALLOC_FREE(qlines);
7672
7673 out:
7674         if (!W_ERROR_IS_OK(result)) {
7675                 TALLOC_FREE(info);
7676                 TALLOC_FREE(qlines);
7677                 *count = 0;
7678                 *info_p = NULL;
7679                 return result;
7680         }
7681
7682         *info_p = info;
7683         *count = numlines;
7684
7685         return WERR_OK;
7686 }
7687
7688 /****************************************************************
7689  _spoolss_EnumPorts
7690 ****************************************************************/
7691
7692 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
7693                           struct spoolss_EnumPorts *r)
7694 {
7695         WERROR result;
7696
7697         /* that's an [in out] buffer */
7698
7699         if (!r->in.buffer && (r->in.offered != 0)) {
7700                 return WERR_INVALID_PARAM;
7701         }
7702
7703         DEBUG(4,("_spoolss_EnumPorts\n"));
7704
7705         *r->out.count = 0;
7706         *r->out.needed = 0;
7707         *r->out.info = NULL;
7708
7709         switch (r->in.level) {
7710         case 1:
7711                 result = enumports_level_1(p->mem_ctx, r->out.info,
7712                                            r->out.count);
7713                 break;
7714         case 2:
7715                 result = enumports_level_2(p->mem_ctx, r->out.info,
7716                                            r->out.count);
7717                 break;
7718         default:
7719                 return WERR_UNKNOWN_LEVEL;
7720         }
7721
7722         if (!W_ERROR_IS_OK(result)) {
7723                 return result;
7724         }
7725
7726         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7727                                                      spoolss_EnumPorts, 
7728                                                      *r->out.info, r->in.level,
7729                                                      *r->out.count);
7730         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7731         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7732
7733         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7734 }
7735
7736 /****************************************************************************
7737 ****************************************************************************/
7738
7739 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
7740                                            const char *server,
7741                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
7742                                            struct spoolss_DeviceMode *devmode,
7743                                            struct security_descriptor *secdesc,
7744                                            struct spoolss_UserLevelCtr *user_ctr,
7745                                            struct policy_handle *handle)
7746 {
7747         struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
7748         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
7749         int     snum;
7750         WERROR err = WERR_OK;
7751
7752         /* samba does not have a concept of local, non-shared printers yet, so
7753          * make sure we always setup sharename - gd */
7754         if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
7755             (info2->printername != NULL && info2->printername[0] != '\0')) {
7756                 DEBUG(5, ("spoolss_addprinterex_level_2: "
7757                         "no sharename has been set, setting printername %s as sharename\n",
7758                         info2->printername));
7759                 info2->sharename = info2->printername;
7760         }
7761
7762         /* check to see if the printer already exists */
7763         if ((snum = print_queue_snum(info2->sharename)) != -1) {
7764                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7765                         info2->sharename));
7766                 return WERR_PRINTER_ALREADY_EXISTS;
7767         }
7768
7769         if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7770                 if ((snum = print_queue_snum(info2->printername)) != -1) {
7771                         DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7772                                 info2->printername));
7773                         return WERR_PRINTER_ALREADY_EXISTS;
7774                 }
7775         }
7776
7777         /* validate printer info struct */
7778         if (!info2->printername || strlen(info2->printername) == 0) {
7779                 return WERR_INVALID_PRINTER_NAME;
7780         }
7781         if (!info2->portname || strlen(info2->portname) == 0) {
7782                 return WERR_UNKNOWN_PORT;
7783         }
7784         if (!info2->drivername || strlen(info2->drivername) == 0) {
7785                 return WERR_UNKNOWN_PRINTER_DRIVER;
7786         }
7787         if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
7788                 return WERR_UNKNOWN_PRINTPROCESSOR;
7789         }
7790
7791         /* FIXME!!!  smbd should check to see if the driver is installed before
7792            trying to add a printer like this  --jerry */
7793
7794         if (*lp_addprinter_cmd() ) {
7795                 if ( !add_printer_hook(p->mem_ctx, p->server_info->ptok,
7796                                        info2, p->client_id->addr,
7797                                        p->msg_ctx) ) {
7798                         return WERR_ACCESS_DENIED;
7799                 }
7800         } else {
7801                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7802                         "smb.conf parameter \"addprinter command\" is defined. This"
7803                         "parameter must exist for this call to succeed\n",
7804                         info2->sharename ));
7805         }
7806
7807         if ((snum = print_queue_snum(info2->sharename)) == -1) {
7808                 return WERR_ACCESS_DENIED;
7809         }
7810
7811         /* you must be a printer admin to add a new printer */
7812         if (!print_access_check(p->server_info,
7813                                 p->msg_ctx,
7814                                 snum,
7815                                 PRINTER_ACCESS_ADMINISTER)) {
7816                 return WERR_ACCESS_DENIED;
7817         }
7818
7819         /*
7820          * Do sanity check on the requested changes for Samba.
7821          */
7822
7823         if (!check_printer_ok(p->mem_ctx, info2, snum)) {
7824                 return WERR_INVALID_PARAM;
7825         }
7826
7827         if (devmode == NULL) {
7828                 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
7829         }
7830
7831         update_dsspooler(p->mem_ctx,
7832                          get_server_info_system(),
7833                          p->msg_ctx,
7834                          0,
7835                          info2,
7836                          NULL);
7837
7838         err = winreg_update_printer(p->mem_ctx,
7839                                     get_server_info_system(),
7840                                     p->msg_ctx,
7841                                     info2->sharename,
7842                                     info2_mask,
7843                                     info2,
7844                                     devmode,
7845                                     secdesc);
7846         if (!W_ERROR_IS_OK(err)) {
7847                 return err;
7848         }
7849
7850         if (!open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER)) {
7851                 /* Handle open failed - remove addition. */
7852                 ZERO_STRUCTP(handle);
7853                 return WERR_ACCESS_DENIED;
7854         }
7855
7856         return WERR_OK;
7857 }
7858
7859 /****************************************************************
7860  _spoolss_AddPrinterEx
7861 ****************************************************************/
7862
7863 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
7864                              struct spoolss_AddPrinterEx *r)
7865 {
7866         switch (r->in.info_ctr->level) {
7867         case 1:
7868                 /* we don't handle yet */
7869                 /* but I know what to do ... */
7870                 return WERR_UNKNOWN_LEVEL;
7871         case 2:
7872                 return spoolss_addprinterex_level_2(p, r->in.server,
7873                                                     r->in.info_ctr,
7874                                                     r->in.devmode_ctr->devmode,
7875                                                     r->in.secdesc_ctr->sd,
7876                                                     r->in.userlevel_ctr,
7877                                                     r->out.handle);
7878         default:
7879                 return WERR_UNKNOWN_LEVEL;
7880         }
7881 }
7882
7883 /****************************************************************
7884  _spoolss_AddPrinter
7885 ****************************************************************/
7886
7887 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
7888                            struct spoolss_AddPrinter *r)
7889 {
7890         struct spoolss_AddPrinterEx a;
7891         struct spoolss_UserLevelCtr userlevel_ctr;
7892
7893         ZERO_STRUCT(userlevel_ctr);
7894
7895         userlevel_ctr.level = 1;
7896
7897         a.in.server             = r->in.server;
7898         a.in.info_ctr           = r->in.info_ctr;
7899         a.in.devmode_ctr        = r->in.devmode_ctr;
7900         a.in.secdesc_ctr        = r->in.secdesc_ctr;
7901         a.in.userlevel_ctr      = &userlevel_ctr;
7902         a.out.handle            = r->out.handle;
7903
7904         return _spoolss_AddPrinterEx(p, &a);
7905 }
7906
7907 /****************************************************************
7908  _spoolss_AddPrinterDriverEx
7909 ****************************************************************/
7910
7911 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
7912                                    struct spoolss_AddPrinterDriverEx *r)
7913 {
7914         WERROR err = WERR_OK;
7915         const char *driver_name = NULL;
7916         uint32_t version;
7917         const char *fn;
7918
7919         switch (p->opnum) {
7920                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7921                         fn = "_spoolss_AddPrinterDriver";
7922                         break;
7923                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7924                         fn = "_spoolss_AddPrinterDriverEx";
7925                         break;
7926                 default:
7927                         return WERR_INVALID_PARAM;
7928         }
7929
7930         /*
7931          * we only support the semantics of AddPrinterDriver()
7932          * i.e. only copy files that are newer than existing ones
7933          */
7934
7935         if (r->in.flags == 0) {
7936                 return WERR_INVALID_PARAM;
7937         }
7938
7939         if (r->in.flags != APD_COPY_NEW_FILES) {
7940                 return WERR_ACCESS_DENIED;
7941         }
7942
7943         /* FIXME */
7944         if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
7945                 /* Clever hack from Martin Zielinski <mz@seh.de>
7946                  * to allow downgrade from level 8 (Vista).
7947                  */
7948                 DEBUG(0,("%s: level %d not yet implemented\n", fn,
7949                         r->in.info_ctr->level));
7950                 return WERR_UNKNOWN_LEVEL;
7951         }
7952
7953         DEBUG(5,("Cleaning driver's information\n"));
7954         err = clean_up_driver_struct(p->mem_ctx, p, r->in.info_ctr);
7955         if (!W_ERROR_IS_OK(err))
7956                 goto done;
7957
7958         DEBUG(5,("Moving driver to final destination\n"));
7959         if( !W_ERROR_IS_OK(err = move_driver_to_download_area(p, r->in.info_ctr,
7960                                                               &err)) ) {
7961                 goto done;
7962         }
7963
7964         err = winreg_add_driver(p->mem_ctx,
7965                                 get_server_info_system(),
7966                                 p->msg_ctx,
7967                                 r->in.info_ctr,
7968                                 &driver_name,
7969                                 &version);
7970         if (!W_ERROR_IS_OK(err)) {
7971                 goto done;
7972         }
7973
7974         /*
7975          * I think this is where he DrvUpgradePrinter() hook would be
7976          * be called in a driver's interface DLL on a Windows NT 4.0/2k
7977          * server.  Right now, we just need to send ourselves a message
7978          * to update each printer bound to this driver.   --jerry
7979          */
7980
7981         if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
7982                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7983                         fn, driver_name));
7984         }
7985
7986 done:
7987         return err;
7988 }
7989
7990 /****************************************************************
7991  _spoolss_AddPrinterDriver
7992 ****************************************************************/
7993
7994 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
7995                                  struct spoolss_AddPrinterDriver *r)
7996 {
7997         struct spoolss_AddPrinterDriverEx a;
7998
7999         switch (r->in.info_ctr->level) {
8000         case 2:
8001         case 3:
8002         case 4:
8003         case 5:
8004                 break;
8005         default:
8006                 return WERR_UNKNOWN_LEVEL;
8007         }
8008
8009         a.in.servername         = r->in.servername;
8010         a.in.info_ctr           = r->in.info_ctr;
8011         a.in.flags              = APD_COPY_NEW_FILES;
8012
8013         return _spoolss_AddPrinterDriverEx(p, &a);
8014 }
8015
8016 /****************************************************************************
8017 ****************************************************************************/
8018
8019 struct _spoolss_paths {
8020         int type;
8021         const char *share;
8022         const char *dir;
8023 };
8024
8025 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8026
8027 static const struct _spoolss_paths spoolss_paths[]= {
8028         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
8029         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
8030 };
8031
8032 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8033                                           const char *servername,
8034                                           const char *environment,
8035                                           int component,
8036                                           char **path)
8037 {
8038         const char *pservername = NULL;
8039         const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
8040         const char *short_archi;
8041
8042         *path = NULL;
8043
8044         /* environment may be empty */
8045         if (environment && strlen(environment)) {
8046                 long_archi = environment;
8047         }
8048
8049         /* servername may be empty */
8050         if (servername && strlen(servername)) {
8051                 pservername = canon_servername(servername);
8052
8053                 if (!is_myname_or_ipaddr(pservername)) {
8054                         return WERR_INVALID_PARAM;
8055                 }
8056         }
8057
8058         if (!(short_archi = get_short_archi(long_archi))) {
8059                 return WERR_INVALID_ENVIRONMENT;
8060         }
8061
8062         switch (component) {
8063         case SPOOLSS_PRTPROCS_PATH:
8064         case SPOOLSS_DRIVER_PATH:
8065                 if (pservername) {
8066                         *path = talloc_asprintf(mem_ctx,
8067                                         "\\\\%s\\%s\\%s",
8068                                         pservername,
8069                                         spoolss_paths[component].share,
8070                                         short_archi);
8071                 } else {
8072                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8073                                         SPOOLSS_DEFAULT_SERVER_PATH,
8074                                         spoolss_paths[component].dir,
8075                                         short_archi);
8076                 }
8077                 break;
8078         default:
8079                 return WERR_INVALID_PARAM;
8080         }
8081
8082         if (!*path) {
8083                 return WERR_NOMEM;
8084         }
8085
8086         return WERR_OK;
8087 }
8088
8089 /****************************************************************************
8090 ****************************************************************************/
8091
8092 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8093                                           const char *servername,
8094                                           const char *environment,
8095                                           struct spoolss_DriverDirectoryInfo1 *r)
8096 {
8097         WERROR werr;
8098         char *path = NULL;
8099
8100         werr = compose_spoolss_server_path(mem_ctx,
8101                                            servername,
8102                                            environment,
8103                                            SPOOLSS_DRIVER_PATH,
8104                                            &path);
8105         if (!W_ERROR_IS_OK(werr)) {
8106                 return werr;
8107         }
8108
8109         DEBUG(4,("printer driver directory: [%s]\n", path));
8110
8111         r->directory_name = path;
8112
8113         return WERR_OK;
8114 }
8115
8116 /****************************************************************
8117  _spoolss_GetPrinterDriverDirectory
8118 ****************************************************************/
8119
8120 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8121                                           struct spoolss_GetPrinterDriverDirectory *r)
8122 {
8123         WERROR werror;
8124
8125         /* that's an [in out] buffer */
8126
8127         if (!r->in.buffer && (r->in.offered != 0)) {
8128                 return WERR_INVALID_PARAM;
8129         }
8130
8131         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8132                 r->in.level));
8133
8134         *r->out.needed = 0;
8135
8136         /* r->in.level is ignored */
8137
8138         werror = getprinterdriverdir_level_1(p->mem_ctx,
8139                                              r->in.server,
8140                                              r->in.environment,
8141                                              &r->out.info->info1);
8142         if (!W_ERROR_IS_OK(werror)) {
8143                 TALLOC_FREE(r->out.info);
8144                 return werror;
8145         }
8146
8147         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo, 
8148                                                r->out.info, r->in.level);
8149         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8150
8151         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8152 }
8153
8154 /****************************************************************
8155  _spoolss_EnumPrinterData
8156 ****************************************************************/
8157
8158 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8159                                 struct spoolss_EnumPrinterData *r)
8160 {
8161         WERROR result;
8162         struct spoolss_EnumPrinterDataEx r2;
8163         uint32_t count;
8164         struct spoolss_PrinterEnumValues *info, *val = NULL;
8165         uint32_t needed;
8166
8167         r2.in.handle    = r->in.handle;
8168         r2.in.key_name  = "PrinterDriverData";
8169         r2.in.offered   = 0;
8170         r2.out.count    = &count;
8171         r2.out.info     = &info;
8172         r2.out.needed   = &needed;
8173
8174         result = _spoolss_EnumPrinterDataEx(p, &r2);
8175         if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8176                 r2.in.offered = needed;
8177                 result = _spoolss_EnumPrinterDataEx(p, &r2);
8178         }
8179         if (!W_ERROR_IS_OK(result)) {
8180                 return result;
8181         }
8182
8183         /*
8184          * The NT machine wants to know the biggest size of value and data
8185          *
8186          * cf: MSDN EnumPrinterData remark section
8187          */
8188
8189         if (!r->in.value_offered && !r->in.data_offered) {
8190                 uint32_t biggest_valuesize = 0;
8191                 uint32_t biggest_datasize = 0;
8192                 int i, name_length;
8193
8194                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8195
8196                 for (i=0; i<count; i++) {
8197
8198                         name_length = strlen(info[i].value_name);
8199                         if (strlen(info[i].value_name) > biggest_valuesize) {
8200                                 biggest_valuesize = name_length;
8201                         }
8202
8203                         if (info[i].data_length > biggest_datasize) {
8204                                 biggest_datasize = info[i].data_length;
8205                         }
8206
8207                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8208                                 biggest_datasize));
8209                 }
8210
8211                 /* the value is an UNICODE string but real_value_size is the length
8212                    in bytes including the trailing 0 */
8213
8214                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8215                 *r->out.data_needed  = biggest_datasize;
8216
8217                 DEBUG(6,("final values: [%d], [%d]\n",
8218                         *r->out.value_needed, *r->out.data_needed));
8219
8220                 return WERR_OK;
8221         }
8222
8223         if (r->in.enum_index < count) {
8224                 val = &info[r->in.enum_index];
8225         }
8226
8227         if (val == NULL) {
8228                 /* out_value should default to "" or else NT4 has
8229                    problems unmarshalling the response */
8230
8231                 if (r->in.value_offered) {
8232                         *r->out.value_needed = 1;
8233                         r->out.value_name = talloc_strdup(r, "");
8234                         if (!r->out.value_name) {
8235                                 return WERR_NOMEM;
8236                         }
8237                 } else {
8238                         r->out.value_name = NULL;
8239                         *r->out.value_needed = 0;
8240                 }
8241
8242                 /* the data is counted in bytes */
8243
8244                 *r->out.data_needed = r->in.data_offered;
8245
8246                 result = WERR_NO_MORE_ITEMS;
8247         } else {
8248                 /*
8249                  * the value is:
8250                  * - counted in bytes in the request
8251                  * - counted in UNICODE chars in the max reply
8252                  * - counted in bytes in the real size
8253                  *
8254                  * take a pause *before* coding not *during* coding
8255                  */
8256
8257                 /* name */
8258                 if (r->in.value_offered) {
8259                         r->out.value_name = talloc_strdup(r, val->value_name);
8260                         if (!r->out.value_name) {
8261                                 return WERR_NOMEM;
8262                         }
8263                         *r->out.value_needed = val->value_name_len;
8264                 } else {
8265                         r->out.value_name = NULL;
8266                         *r->out.value_needed = 0;
8267                 }
8268
8269                 /* type */
8270
8271                 *r->out.type = val->type;
8272
8273                 /* data - counted in bytes */
8274
8275                 /*
8276                  * See the section "Dynamically Typed Query Parameters"
8277                  * in MS-RPRN.
8278                  */
8279
8280                 if (r->out.data && val->data && val->data->data &&
8281                                 val->data_length && r->in.data_offered) {
8282                         memcpy(r->out.data, val->data->data,
8283                                 MIN(val->data_length,r->in.data_offered));
8284                 }
8285
8286                 *r->out.data_needed = val->data_length;
8287
8288                 result = WERR_OK;
8289         }
8290
8291         return result;
8292 }
8293
8294 /****************************************************************
8295  _spoolss_SetPrinterData
8296 ****************************************************************/
8297
8298 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8299                                struct spoolss_SetPrinterData *r)
8300 {
8301         struct spoolss_SetPrinterDataEx r2;
8302
8303         r2.in.handle            = r->in.handle;
8304         r2.in.key_name          = "PrinterDriverData";
8305         r2.in.value_name        = r->in.value_name;
8306         r2.in.type              = r->in.type;
8307         r2.in.data              = r->in.data;
8308         r2.in.offered           = r->in.offered;
8309
8310         return _spoolss_SetPrinterDataEx(p, &r2);
8311 }
8312
8313 /****************************************************************
8314  _spoolss_ResetPrinter
8315 ****************************************************************/
8316
8317 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8318                              struct spoolss_ResetPrinter *r)
8319 {
8320         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8321         int             snum;
8322
8323         DEBUG(5,("_spoolss_ResetPrinter\n"));
8324
8325         /*
8326          * All we do is to check to see if the handle and queue is valid.
8327          * This call really doesn't mean anything to us because we only
8328          * support RAW printing.   --jerry
8329          */
8330
8331         if (!Printer) {
8332                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8333                         OUR_HANDLE(r->in.handle)));
8334                 return WERR_BADFID;
8335         }
8336
8337         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8338                 return WERR_BADFID;
8339
8340
8341         /* blindly return success */
8342         return WERR_OK;
8343 }
8344
8345 /****************************************************************
8346  _spoolss_DeletePrinterData
8347 ****************************************************************/
8348
8349 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8350                                   struct spoolss_DeletePrinterData *r)
8351 {
8352         struct spoolss_DeletePrinterDataEx r2;
8353
8354         r2.in.handle            = r->in.handle;
8355         r2.in.key_name          = "PrinterDriverData";
8356         r2.in.value_name        = r->in.value_name;
8357
8358         return _spoolss_DeletePrinterDataEx(p, &r2);
8359 }
8360
8361 /****************************************************************
8362  _spoolss_AddForm
8363 ****************************************************************/
8364
8365 WERROR _spoolss_AddForm(struct pipes_struct *p,
8366                         struct spoolss_AddForm *r)
8367 {
8368         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8369         int snum = -1;
8370         WERROR status = WERR_OK;
8371
8372         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8373
8374         DEBUG(5,("_spoolss_AddForm\n"));
8375
8376         if (!Printer) {
8377                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8378                         OUR_HANDLE(r->in.handle)));
8379                 return WERR_BADFID;
8380         }
8381
8382         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8383            and not a printer admin, then fail */
8384
8385         if ((p->server_info->utok.uid != sec_initial_uid()) &&
8386             !security_token_has_privilege(p->server_info->ptok, SEC_PRIV_PRINT_OPERATOR) &&
8387             !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8388                                           p->server_info->info3->base.domain.string,
8389                                           NULL,
8390                                           p->server_info->ptok,
8391                                           lp_printer_admin(snum))) {
8392                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8393                 return WERR_ACCESS_DENIED;
8394         }
8395
8396         switch (form->flags) {
8397         case SPOOLSS_FORM_USER:
8398         case SPOOLSS_FORM_BUILTIN:
8399         case SPOOLSS_FORM_PRINTER:
8400                 break;
8401         default:
8402                 return WERR_INVALID_PARAM;
8403         }
8404
8405         status = winreg_printer_addform1(p->mem_ctx,
8406                                          get_server_info_system(),
8407                                          p->msg_ctx,
8408                                          form);
8409         if (!W_ERROR_IS_OK(status)) {
8410                 return status;
8411         }
8412
8413         /*
8414          * ChangeID must always be set if this is a printer
8415          */
8416         if (Printer->printer_type == SPLHND_PRINTER) {
8417                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8418                         return WERR_BADFID;
8419                 }
8420
8421                 status = winreg_printer_update_changeid(p->mem_ctx,
8422                                                         get_server_info_system(),
8423                                                         p->msg_ctx,
8424                                                         lp_const_servicename(snum));
8425                 if (!W_ERROR_IS_OK(status)) {
8426                         return status;
8427                 }
8428         }
8429
8430         return status;
8431 }
8432
8433 /****************************************************************
8434  _spoolss_DeleteForm
8435 ****************************************************************/
8436
8437 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8438                            struct spoolss_DeleteForm *r)
8439 {
8440         const char *form_name = r->in.form_name;
8441         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8442         int snum = -1;
8443         WERROR status = WERR_OK;
8444
8445         DEBUG(5,("_spoolss_DeleteForm\n"));
8446
8447         if (!Printer) {
8448                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8449                         OUR_HANDLE(r->in.handle)));
8450                 return WERR_BADFID;
8451         }
8452
8453         if ((p->server_info->utok.uid != sec_initial_uid()) &&
8454             !security_token_has_privilege(p->server_info->ptok, SEC_PRIV_PRINT_OPERATOR) &&
8455             !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8456                                           p->server_info->info3->base.domain.string,
8457                                           NULL,
8458                                           p->server_info->ptok,
8459                                           lp_printer_admin(snum))) {
8460                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8461                 return WERR_ACCESS_DENIED;
8462         }
8463
8464         status = winreg_printer_deleteform1(p->mem_ctx,
8465                                             get_server_info_system(),
8466                                             p->msg_ctx,
8467                                             form_name);
8468         if (!W_ERROR_IS_OK(status)) {
8469                 return status;
8470         }
8471
8472         /*
8473          * ChangeID must always be set if this is a printer
8474          */
8475         if (Printer->printer_type == SPLHND_PRINTER) {
8476                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8477                         return WERR_BADFID;
8478                 }
8479
8480                 status = winreg_printer_update_changeid(p->mem_ctx,
8481                                                         get_server_info_system(),
8482                                                         p->msg_ctx,
8483                                                         lp_const_servicename(snum));
8484                 if (!W_ERROR_IS_OK(status)) {
8485                         return status;
8486                 }
8487         }
8488
8489         return status;
8490 }
8491
8492 /****************************************************************
8493  _spoolss_SetForm
8494 ****************************************************************/
8495
8496 WERROR _spoolss_SetForm(struct pipes_struct *p,
8497                         struct spoolss_SetForm *r)
8498 {
8499         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8500         const char *form_name = r->in.form_name;
8501         int snum = -1;
8502         WERROR status = WERR_OK;
8503
8504         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8505
8506         DEBUG(5,("_spoolss_SetForm\n"));
8507
8508         if (!Printer) {
8509                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8510                         OUR_HANDLE(r->in.handle)));
8511                 return WERR_BADFID;
8512         }
8513
8514         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8515            and not a printer admin, then fail */
8516
8517         if ((p->server_info->utok.uid != sec_initial_uid()) &&
8518              !security_token_has_privilege(p->server_info->ptok, SEC_PRIV_PRINT_OPERATOR) &&
8519              !token_contains_name_in_list(uidtoname(p->server_info->utok.uid),
8520                                           p->server_info->info3->base.domain.string,
8521                                           NULL,
8522                                           p->server_info->ptok,
8523                                           lp_printer_admin(snum))) {
8524                 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8525                 return WERR_ACCESS_DENIED;
8526         }
8527
8528         status = winreg_printer_setform1(p->mem_ctx,
8529                                          get_server_info_system(),
8530                                          p->msg_ctx,
8531                                          form_name,
8532                                          form);
8533         if (!W_ERROR_IS_OK(status)) {
8534                 return status;
8535         }
8536
8537         /*
8538          * ChangeID must always be set if this is a printer
8539          */
8540         if (Printer->printer_type == SPLHND_PRINTER) {
8541                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8542                         return WERR_BADFID;
8543                 }
8544
8545                 status = winreg_printer_update_changeid(p->mem_ctx,
8546                                                         get_server_info_system(),
8547                                                         p->msg_ctx,
8548                                                         lp_const_servicename(snum));
8549                 if (!W_ERROR_IS_OK(status)) {
8550                         return status;
8551                 }
8552         }
8553
8554         return status;
8555 }
8556
8557 /****************************************************************************
8558  fill_print_processor1
8559 ****************************************************************************/
8560
8561 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8562                                     struct spoolss_PrintProcessorInfo1 *r,
8563                                     const char *print_processor_name)
8564 {
8565         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8566         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8567
8568         return WERR_OK;
8569 }
8570
8571 /****************************************************************************
8572  enumprintprocessors level 1.
8573 ****************************************************************************/
8574
8575 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8576                                           union spoolss_PrintProcessorInfo **info_p,
8577                                           uint32_t *count)
8578 {
8579         union spoolss_PrintProcessorInfo *info;
8580         WERROR result;
8581
8582         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8583         W_ERROR_HAVE_NO_MEMORY(info);
8584
8585         *count = 1;
8586
8587         result = fill_print_processor1(info, &info[0].info1, "winprint");
8588         if (!W_ERROR_IS_OK(result)) {
8589                 goto out;
8590         }
8591
8592  out:
8593         if (!W_ERROR_IS_OK(result)) {
8594                 TALLOC_FREE(info);
8595                 *count = 0;
8596                 return result;
8597         }
8598
8599         *info_p = info;
8600
8601         return WERR_OK;
8602 }
8603
8604 /****************************************************************
8605  _spoolss_EnumPrintProcessors
8606 ****************************************************************/
8607
8608 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
8609                                     struct spoolss_EnumPrintProcessors *r)
8610 {
8611         WERROR result;
8612
8613         /* that's an [in out] buffer */
8614
8615         if (!r->in.buffer && (r->in.offered != 0)) {
8616                 return WERR_INVALID_PARAM;
8617         }
8618
8619         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8620
8621         /*
8622          * Enumerate the print processors ...
8623          *
8624          * Just reply with "winprint", to keep NT happy
8625          * and I can use my nice printer checker.
8626          */
8627
8628         *r->out.count = 0;
8629         *r->out.needed = 0;
8630         *r->out.info = NULL;
8631
8632         if (!get_short_archi(r->in.environment)) {
8633                 return WERR_INVALID_ENVIRONMENT;
8634         }
8635
8636         switch (r->in.level) {
8637         case 1:
8638                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8639                                                      r->out.count);
8640                 break;
8641         default:
8642                 return WERR_UNKNOWN_LEVEL;
8643         }
8644
8645         if (!W_ERROR_IS_OK(result)) {
8646                 return result;
8647         }
8648
8649         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8650                                                      spoolss_EnumPrintProcessors,
8651                                                      *r->out.info, r->in.level,
8652                                                      *r->out.count);
8653         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8654         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8655
8656         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8657 }
8658
8659 /****************************************************************************
8660  fill_printprocdatatype1
8661 ****************************************************************************/
8662
8663 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8664                                       struct spoolss_PrintProcDataTypesInfo1 *r,
8665                                       const char *name_array)
8666 {
8667         r->name_array = talloc_strdup(mem_ctx, name_array);
8668         W_ERROR_HAVE_NO_MEMORY(r->name_array);
8669
8670         return WERR_OK;
8671 }
8672
8673 /****************************************************************************
8674  enumprintprocdatatypes level 1.
8675 ****************************************************************************/
8676
8677 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8678                                              union spoolss_PrintProcDataTypesInfo **info_p,
8679                                              uint32_t *count)
8680 {
8681         WERROR result;
8682         union spoolss_PrintProcDataTypesInfo *info;
8683
8684         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8685         W_ERROR_HAVE_NO_MEMORY(info);
8686
8687         *count = 1;
8688
8689         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8690         if (!W_ERROR_IS_OK(result)) {
8691                 goto out;
8692         }
8693
8694  out:
8695         if (!W_ERROR_IS_OK(result)) {
8696                 TALLOC_FREE(info);
8697                 *count = 0;
8698                 return result;
8699         }
8700
8701         *info_p = info;
8702
8703         return WERR_OK;
8704 }
8705
8706 /****************************************************************
8707  _spoolss_EnumPrintProcDataTypes
8708 ****************************************************************/
8709
8710 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
8711                                        struct spoolss_EnumPrintProcDataTypes *r)
8712 {
8713         WERROR result;
8714
8715         /* that's an [in out] buffer */
8716
8717         if (!r->in.buffer && (r->in.offered != 0)) {
8718                 return WERR_INVALID_PARAM;
8719         }
8720
8721         DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8722
8723         *r->out.count = 0;
8724         *r->out.needed = 0;
8725         *r->out.info = NULL;
8726
8727         if (r->in.print_processor_name == NULL ||
8728             !strequal(r->in.print_processor_name, "winprint")) {
8729                 return WERR_UNKNOWN_PRINTPROCESSOR;
8730         }
8731
8732         switch (r->in.level) {
8733         case 1:
8734                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8735                                                         r->out.count);
8736                 break;
8737         default:
8738                 return WERR_UNKNOWN_LEVEL;
8739         }
8740
8741         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8742                                                      spoolss_EnumPrintProcDataTypes, 
8743                                                      *r->out.info, r->in.level,
8744                                                      *r->out.count);
8745         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8746         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8747
8748         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8749 }
8750
8751 /****************************************************************************
8752  fill_monitor_1
8753 ****************************************************************************/
8754
8755 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8756                              struct spoolss_MonitorInfo1 *r,
8757                              const char *monitor_name)
8758 {
8759         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8760         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8761
8762         return WERR_OK;
8763 }
8764
8765 /****************************************************************************
8766  fill_monitor_2
8767 ****************************************************************************/
8768
8769 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8770                              struct spoolss_MonitorInfo2 *r,
8771                              const char *monitor_name,
8772                              const char *environment,
8773                              const char *dll_name)
8774 {
8775         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8776         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8777         r->environment                  = talloc_strdup(mem_ctx, environment);
8778         W_ERROR_HAVE_NO_MEMORY(r->environment);
8779         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
8780         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8781
8782         return WERR_OK;
8783 }
8784
8785 /****************************************************************************
8786  enumprintmonitors level 1.
8787 ****************************************************************************/
8788
8789 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8790                                         union spoolss_MonitorInfo **info_p,
8791                                         uint32_t *count)
8792 {
8793         union spoolss_MonitorInfo *info;
8794         WERROR result = WERR_OK;
8795
8796         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8797         W_ERROR_HAVE_NO_MEMORY(info);
8798
8799         *count = 2;
8800
8801         result = fill_monitor_1(info, &info[0].info1,
8802                                 SPL_LOCAL_PORT);
8803         if (!W_ERROR_IS_OK(result)) {
8804                 goto out;
8805         }
8806
8807         result = fill_monitor_1(info, &info[1].info1,
8808                                 SPL_TCPIP_PORT);
8809         if (!W_ERROR_IS_OK(result)) {
8810                 goto out;
8811         }
8812
8813 out:
8814         if (!W_ERROR_IS_OK(result)) {
8815                 TALLOC_FREE(info);
8816                 *count = 0;
8817                 return result;
8818         }
8819
8820         *info_p = info;
8821
8822         return WERR_OK;
8823 }
8824
8825 /****************************************************************************
8826  enumprintmonitors level 2.
8827 ****************************************************************************/
8828
8829 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8830                                         union spoolss_MonitorInfo **info_p,
8831                                         uint32_t *count)
8832 {
8833         union spoolss_MonitorInfo *info;
8834         WERROR result = WERR_OK;
8835
8836         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8837         W_ERROR_HAVE_NO_MEMORY(info);
8838
8839         *count = 2;
8840
8841         result = fill_monitor_2(info, &info[0].info2,
8842                                 SPL_LOCAL_PORT,
8843                                 "Windows NT X86", /* FIXME */
8844                                 "localmon.dll");
8845         if (!W_ERROR_IS_OK(result)) {
8846                 goto out;
8847         }
8848
8849         result = fill_monitor_2(info, &info[1].info2,
8850                                 SPL_TCPIP_PORT,
8851                                 "Windows NT X86", /* FIXME */
8852                                 "tcpmon.dll");
8853         if (!W_ERROR_IS_OK(result)) {
8854                 goto out;
8855         }
8856
8857 out:
8858         if (!W_ERROR_IS_OK(result)) {
8859                 TALLOC_FREE(info);
8860                 *count = 0;
8861                 return result;
8862         }
8863
8864         *info_p = info;
8865
8866         return WERR_OK;
8867 }
8868
8869 /****************************************************************
8870  _spoolss_EnumMonitors
8871 ****************************************************************/
8872
8873 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
8874                              struct spoolss_EnumMonitors *r)
8875 {
8876         WERROR result;
8877
8878         /* that's an [in out] buffer */
8879
8880         if (!r->in.buffer && (r->in.offered != 0)) {
8881                 return WERR_INVALID_PARAM;
8882         }
8883
8884         DEBUG(5,("_spoolss_EnumMonitors\n"));
8885
8886         /*
8887          * Enumerate the print monitors ...
8888          *
8889          * Just reply with "Local Port", to keep NT happy
8890          * and I can use my nice printer checker.
8891          */
8892
8893         *r->out.count = 0;
8894         *r->out.needed = 0;
8895         *r->out.info = NULL;
8896
8897         switch (r->in.level) {
8898         case 1:
8899                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8900                                                    r->out.count);
8901                 break;
8902         case 2:
8903                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8904                                                    r->out.count);
8905                 break;
8906         default:
8907                 return WERR_UNKNOWN_LEVEL;
8908         }
8909
8910         if (!W_ERROR_IS_OK(result)) {
8911                 return result;
8912         }
8913
8914         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8915                                                      spoolss_EnumMonitors, 
8916                                                      *r->out.info, r->in.level,
8917                                                      *r->out.count);
8918         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8919         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8920
8921         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8922 }
8923
8924 /****************************************************************************
8925 ****************************************************************************/
8926
8927 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8928                              const print_queue_struct *queue,
8929                              int count, int snum,
8930                              struct spoolss_PrinterInfo2 *pinfo2,
8931                              uint32_t jobid,
8932                              struct spoolss_JobInfo1 *r)
8933 {
8934         int i = 0;
8935         bool found = false;
8936
8937         for (i=0; i<count; i++) {
8938                 if (queue[i].job == (int)jobid) {
8939                         found = true;
8940                         break;
8941                 }
8942         }
8943
8944         if (found == false) {
8945                 /* NT treats not found as bad param... yet another bad choice */
8946                 return WERR_INVALID_PARAM;
8947         }
8948
8949         return fill_job_info1(mem_ctx,
8950                               r,
8951                               &queue[i],
8952                               i,
8953                               snum,
8954                               pinfo2);
8955 }
8956
8957 /****************************************************************************
8958 ****************************************************************************/
8959
8960 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
8961                              const print_queue_struct *queue,
8962                              int count, int snum,
8963                              struct spoolss_PrinterInfo2 *pinfo2,
8964                              uint32_t jobid,
8965                              struct spoolss_JobInfo2 *r)
8966 {
8967         int i = 0;
8968         bool found = false;
8969         struct spoolss_DeviceMode *devmode;
8970         WERROR result;
8971
8972         for (i=0; i<count; i++) {
8973                 if (queue[i].job == (int)jobid) {
8974                         found = true;
8975                         break;
8976                 }
8977         }
8978
8979         if (found == false) {
8980                 /* NT treats not found as bad param... yet another bad
8981                    choice */
8982                 return WERR_INVALID_PARAM;
8983         }
8984
8985         /*
8986          * if the print job does not have a DEVMODE associated with it,
8987          * just use the one for the printer. A NULL devicemode is not
8988          *  a failure condition
8989          */
8990
8991         devmode = print_job_devmode(lp_const_servicename(snum), jobid);
8992         if (!devmode) {
8993                 result = spoolss_create_default_devmode(mem_ctx,
8994                                                 pinfo2->printername,
8995                                                 &devmode);
8996                 if (!W_ERROR_IS_OK(result)) {
8997                         DEBUG(3, ("Can't proceed w/o a devmode!"));
8998                         return result;
8999                 }
9000         }
9001
9002         return fill_job_info2(mem_ctx,
9003                               r,
9004                               &queue[i],
9005                               i,
9006                               snum,
9007                               pinfo2,
9008                               devmode);
9009 }
9010
9011 /****************************************************************
9012  _spoolss_GetJob
9013 ****************************************************************/
9014
9015 WERROR _spoolss_GetJob(struct pipes_struct *p,
9016                        struct spoolss_GetJob *r)
9017 {
9018         WERROR result = WERR_OK;
9019         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9020         int snum;
9021         int count;
9022         print_queue_struct      *queue = NULL;
9023         print_status_struct prt_status;
9024
9025         /* that's an [in out] buffer */
9026
9027         if (!r->in.buffer && (r->in.offered != 0)) {
9028                 return WERR_INVALID_PARAM;
9029         }
9030
9031         DEBUG(5,("_spoolss_GetJob\n"));
9032
9033         *r->out.needed = 0;
9034
9035         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9036                 return WERR_BADFID;
9037         }
9038
9039         result = winreg_get_printer(p->mem_ctx,
9040                                     get_server_info_system(),
9041                                     p->msg_ctx,
9042                                     lp_const_servicename(snum),
9043                                     &pinfo2);
9044         if (!W_ERROR_IS_OK(result)) {
9045                 return result;
9046         }
9047
9048         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9049
9050         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9051                      count, prt_status.status, prt_status.message));
9052
9053         switch (r->in.level) {
9054         case 1:
9055                 result = getjob_level_1(p->mem_ctx,
9056                                         queue, count, snum, pinfo2,
9057                                         r->in.job_id, &r->out.info->info1);
9058                 break;
9059         case 2:
9060                 result = getjob_level_2(p->mem_ctx,
9061                                         queue, count, snum, pinfo2,
9062                                         r->in.job_id, &r->out.info->info2);
9063                 break;
9064         default:
9065                 result = WERR_UNKNOWN_LEVEL;
9066                 break;
9067         }
9068
9069         SAFE_FREE(queue);
9070         TALLOC_FREE(pinfo2);
9071
9072         if (!W_ERROR_IS_OK(result)) {
9073                 TALLOC_FREE(r->out.info);
9074                 return result;
9075         }
9076
9077         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9078                                                                                    r->in.level);
9079         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9080
9081         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9082 }
9083
9084 /****************************************************************
9085  _spoolss_GetPrinterDataEx
9086 ****************************************************************/
9087
9088 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9089                                  struct spoolss_GetPrinterDataEx *r)
9090 {
9091
9092         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9093         const char *printer;
9094         int                     snum = 0;
9095         WERROR result = WERR_OK;
9096         DATA_BLOB blob;
9097         enum winreg_Type val_type;
9098         uint8_t *val_data;
9099         uint32_t val_size;
9100
9101
9102         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9103
9104         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9105                 r->in.key_name, r->in.value_name));
9106
9107         /* in case of problem, return some default values */
9108
9109         *r->out.needed  = 0;
9110         *r->out.type    = REG_NONE;
9111
9112         if (!Printer) {
9113                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9114                         OUR_HANDLE(r->in.handle)));
9115                 result = WERR_BADFID;
9116                 goto done;
9117         }
9118
9119         /* Is the handle to a printer or to the server? */
9120
9121         if (Printer->printer_type == SPLHND_SERVER) {
9122
9123                 union spoolss_PrinterData data;
9124
9125                 result = getprinterdata_printer_server(p->mem_ctx,
9126                                                        r->in.value_name,
9127                                                        r->out.type,
9128                                                        &data);
9129                 if (!W_ERROR_IS_OK(result)) {
9130                         return result;
9131                 }
9132
9133                 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
9134                                                   *r->out.type, &data);
9135                 if (!W_ERROR_IS_OK(result)) {
9136                         return result;
9137                 }
9138
9139                 *r->out.needed = blob.length;
9140
9141                 if (r->in.offered >= *r->out.needed) {
9142                         memcpy(r->out.data, blob.data, blob.length);
9143                 }
9144
9145                 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9146         }
9147
9148         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9149                 return WERR_BADFID;
9150         }
9151         printer = lp_const_servicename(snum);
9152
9153         /* check to see if the keyname is valid */
9154         if (!strlen(r->in.key_name)) {
9155                 return WERR_INVALID_PARAM;
9156         }
9157
9158         /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9159         if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9160             strequal(r->in.value_name, "ChangeId")) {
9161                 *r->out.type = REG_DWORD;
9162                 *r->out.needed = 4;
9163                 if (r->in.offered >= *r->out.needed) {
9164                         uint32_t changeid = 0;
9165
9166                         result = winreg_printer_get_changeid(p->mem_ctx,
9167                                                              get_server_info_system(),
9168                                                              p->msg_ctx,
9169                                                              printer,
9170                                                              &changeid);
9171                         if (!W_ERROR_IS_OK(result)) {
9172                                 return result;
9173                         }
9174
9175                         SIVAL(r->out.data, 0, changeid);
9176                         result = WERR_OK;
9177                 }
9178                 goto done;
9179         }
9180
9181         result = winreg_get_printer_dataex(p->mem_ctx,
9182                                            get_server_info_system(),
9183                                            p->msg_ctx,
9184                                            printer,
9185                                            r->in.key_name,
9186                                            r->in.value_name,
9187                                            &val_type,
9188                                            &val_data,
9189                                            &val_size);
9190         if (!W_ERROR_IS_OK(result)) {
9191                 return result;
9192         }
9193
9194         *r->out.needed = val_size;
9195         *r->out.type = val_type;
9196
9197         if (r->in.offered >= *r->out.needed) {
9198                 memcpy(r->out.data, val_data, val_size);
9199         }
9200
9201  done:
9202         *r->out.type    = SPOOLSS_BUFFER_OK(*r->out.type, REG_NONE);
9203         r->out.data     = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
9204
9205         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9206 }
9207
9208 /****************************************************************
9209  _spoolss_SetPrinterDataEx
9210 ****************************************************************/
9211
9212 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9213                                  struct spoolss_SetPrinterDataEx *r)
9214 {
9215         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9216         int                     snum = 0;
9217         WERROR                  result = WERR_OK;
9218         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9219         char                    *oid_string;
9220
9221         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9222
9223         /* From MSDN documentation of SetPrinterDataEx: pass request to
9224            SetPrinterData if key is "PrinterDriverData" */
9225
9226         if (!Printer) {
9227                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9228                         OUR_HANDLE(r->in.handle)));
9229                 return WERR_BADFID;
9230         }
9231
9232         if (Printer->printer_type == SPLHND_SERVER) {
9233                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9234                         "Not implemented for server handles yet\n"));
9235                 return WERR_INVALID_PARAM;
9236         }
9237
9238         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9239                 return WERR_BADFID;
9240         }
9241
9242         /*
9243          * Access check : NT returns "access denied" if you make a
9244          * SetPrinterData call without the necessary privildge.
9245          * we were originally returning OK if nothing changed
9246          * which made Win2k issue **a lot** of SetPrinterData
9247          * when connecting to a printer  --jerry
9248          */
9249
9250         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9251                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9252                         "change denied by handle access permissions\n"));
9253                 return WERR_ACCESS_DENIED;
9254         }
9255
9256         result = winreg_get_printer(Printer,
9257                                     get_server_info_system(),
9258                                     p->msg_ctx,
9259                                     lp_servicename(snum),
9260                                     &pinfo2);
9261         if (!W_ERROR_IS_OK(result)) {
9262                 return result;
9263         }
9264
9265         /* check for OID in valuename */
9266
9267         oid_string = strchr(r->in.value_name, ',');
9268         if (oid_string) {
9269                 *oid_string = '\0';
9270                 oid_string++;
9271         }
9272
9273         /* save the registry data */
9274
9275         result = winreg_set_printer_dataex(p->mem_ctx,
9276                                            get_server_info_system(),
9277                                            p->msg_ctx,
9278                                            pinfo2->sharename,
9279                                            r->in.key_name,
9280                                            r->in.value_name,
9281                                            r->in.type,
9282                                            r->in.data,
9283                                            r->in.offered);
9284
9285         if (W_ERROR_IS_OK(result)) {
9286                 /* save the OID if one was specified */
9287                 if (oid_string) {
9288                         char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9289                                 r->in.key_name, SPOOL_OID_KEY);
9290                         if (!str) {
9291                                 result = WERR_NOMEM;
9292                                 goto done;
9293                         }
9294
9295                         /*
9296                          * I'm not checking the status here on purpose.  Don't know
9297                          * if this is right, but I'm returning the status from the
9298                          * previous set_printer_dataex() call.  I have no idea if
9299                          * this is right.    --jerry
9300                          */
9301                         winreg_set_printer_dataex(p->mem_ctx,
9302                                                   get_server_info_system(),
9303                                                   p->msg_ctx,
9304                                                   pinfo2->sharename,
9305                                                   str,
9306                                                   r->in.value_name,
9307                                                   REG_SZ,
9308                                                   (uint8_t *) oid_string,
9309                                                   strlen(oid_string) + 1);
9310                 }
9311
9312                 result = winreg_printer_update_changeid(p->mem_ctx,
9313                                                         get_server_info_system(),
9314                                                         p->msg_ctx,
9315                                                         lp_const_servicename(snum));
9316
9317         }
9318
9319 done:
9320         talloc_free(pinfo2);
9321         return result;
9322 }
9323
9324 /****************************************************************
9325  _spoolss_DeletePrinterDataEx
9326 ****************************************************************/
9327
9328 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9329                                     struct spoolss_DeletePrinterDataEx *r)
9330 {
9331         const char *printer;
9332         int             snum=0;
9333         WERROR          status = WERR_OK;
9334         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9335
9336         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9337
9338         if (!Printer) {
9339                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9340                         "Invalid handle (%s:%u:%u).\n",
9341                         OUR_HANDLE(r->in.handle)));
9342                 return WERR_BADFID;
9343         }
9344
9345         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9346                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9347                         "printer properties change denied by handle\n"));
9348                 return WERR_ACCESS_DENIED;
9349         }
9350
9351         if (!r->in.value_name || !r->in.key_name) {
9352                 return WERR_NOMEM;
9353         }
9354
9355         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9356                 return WERR_BADFID;
9357         }
9358         printer = lp_const_servicename(snum);
9359
9360         status = winreg_delete_printer_dataex(p->mem_ctx,
9361                                               get_server_info_system(),
9362                                               p->msg_ctx,
9363                                               printer,
9364                                               r->in.key_name,
9365                                               r->in.value_name);
9366         if (W_ERROR_IS_OK(status)) {
9367                 status = winreg_printer_update_changeid(p->mem_ctx,
9368                                                         get_server_info_system(),
9369                                                         p->msg_ctx,
9370                                                         printer);
9371         }
9372
9373         return status;
9374 }
9375
9376 /****************************************************************
9377  _spoolss_EnumPrinterKey
9378 ****************************************************************/
9379
9380 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9381                                struct spoolss_EnumPrinterKey *r)
9382 {
9383         uint32_t        num_keys;
9384         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9385         int             snum = 0;
9386         WERROR          result = WERR_BADFILE;
9387         const char **array = NULL;
9388         DATA_BLOB blob;
9389
9390         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9391
9392         if (!Printer) {
9393                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9394                         OUR_HANDLE(r->in.handle)));
9395                 return WERR_BADFID;
9396         }
9397
9398         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9399                 return WERR_BADFID;
9400         }
9401
9402         result = winreg_enum_printer_key(p->mem_ctx,
9403                                          get_server_info_system(),
9404                                          p->msg_ctx,
9405                                          lp_const_servicename(snum),
9406                                          r->in.key_name,
9407                                          &num_keys,
9408                                          &array);
9409         if (!W_ERROR_IS_OK(result)) {
9410                 goto done;
9411         }
9412
9413         if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9414                 result = WERR_NOMEM;
9415                 goto done;
9416         }
9417
9418         *r->out._ndr_size = r->in.offered / 2;
9419         *r->out.needed = blob.length;
9420
9421         if (r->in.offered < *r->out.needed) {
9422                 result = WERR_MORE_DATA;
9423         } else {
9424                 result = WERR_OK;
9425                 r->out.key_buffer->string_array = array;
9426         }
9427
9428  done:
9429         if (!W_ERROR_IS_OK(result)) {
9430                 TALLOC_FREE(array);
9431                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9432                         *r->out.needed = 0;
9433                 }
9434         }
9435
9436         return result;
9437 }
9438
9439 /****************************************************************
9440  _spoolss_DeletePrinterKey
9441 ****************************************************************/
9442
9443 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9444                                  struct spoolss_DeletePrinterKey *r)
9445 {
9446         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9447         int                     snum=0;
9448         WERROR                  status;
9449         const char *printer;
9450
9451         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9452
9453         if (!Printer) {
9454                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9455                         OUR_HANDLE(r->in.handle)));
9456                 return WERR_BADFID;
9457         }
9458
9459         /* if keyname == NULL, return error */
9460         if ( !r->in.key_name )
9461                 return WERR_INVALID_PARAM;
9462
9463         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9464                 return WERR_BADFID;
9465         }
9466
9467         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9468                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9469                         "printer properties change denied by handle\n"));
9470                 return WERR_ACCESS_DENIED;
9471         }
9472
9473         printer = lp_const_servicename(snum);
9474
9475         /* delete the key and all subkeys */
9476         status = winreg_delete_printer_key(p->mem_ctx,
9477                                            get_server_info_system(),
9478                                            p->msg_ctx,
9479                                            printer,
9480                                            r->in.key_name);
9481         if (W_ERROR_IS_OK(status)) {
9482                 status = winreg_printer_update_changeid(p->mem_ctx,
9483                                                         get_server_info_system(),
9484                                                         p->msg_ctx,
9485                                                         printer);
9486         }
9487
9488         return status;
9489 }
9490
9491 /****************************************************************
9492  _spoolss_EnumPrinterDataEx
9493 ****************************************************************/
9494
9495 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
9496                                   struct spoolss_EnumPrinterDataEx *r)
9497 {
9498         uint32_t        count = 0;
9499         struct spoolss_PrinterEnumValues *info = NULL;
9500         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9501         int             snum;
9502         WERROR          result;
9503
9504         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9505
9506         *r->out.count = 0;
9507         *r->out.needed = 0;
9508         *r->out.info = NULL;
9509
9510         if (!Printer) {
9511                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9512                         OUR_HANDLE(r->in.handle)));
9513                 return WERR_BADFID;
9514         }
9515
9516         /*
9517          * first check for a keyname of NULL or "".  Win2k seems to send
9518          * this a lot and we should send back WERR_INVALID_PARAM
9519          * no need to spend time looking up the printer in this case.
9520          * --jerry
9521          */
9522
9523         if (!strlen(r->in.key_name)) {
9524                 result = WERR_INVALID_PARAM;
9525                 goto done;
9526         }
9527
9528         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9529                 return WERR_BADFID;
9530         }
9531
9532         /* now look for a match on the key name */
9533         result = winreg_enum_printer_dataex(p->mem_ctx,
9534                                             get_server_info_system(),
9535                                             p->msg_ctx,
9536                                             lp_const_servicename(snum),
9537                                             r->in.key_name,
9538                                             &count,
9539                                             &info);
9540         if (!W_ERROR_IS_OK(result)) {
9541                 goto done;
9542         }
9543
9544 #if 0 /* FIXME - gd */
9545         /* housekeeping information in the reply */
9546
9547         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9548          * the hand marshalled container size is a multiple
9549          * of 4 bytes for RPC alignment.
9550          */
9551
9552         if (needed % 4) {
9553                 needed += 4-(needed % 4);
9554         }
9555 #endif
9556         *r->out.count   = count;
9557         *r->out.info    = info;
9558
9559  done:
9560         if (!W_ERROR_IS_OK(result)) {
9561                 return result;
9562         }
9563
9564         *r->out.needed  = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9565                                                spoolss_EnumPrinterDataEx, 
9566                                                *r->out.info,
9567                                                *r->out.count);
9568         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9569         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9570
9571         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9572 }
9573
9574 /****************************************************************************
9575 ****************************************************************************/
9576
9577 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9578                                                  const char *servername,
9579                                                  const char *environment,
9580                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
9581 {
9582         WERROR werr;
9583         char *path = NULL;
9584
9585         werr = compose_spoolss_server_path(mem_ctx,
9586                                            servername,
9587                                            environment,
9588                                            SPOOLSS_PRTPROCS_PATH,
9589                                            &path);
9590         if (!W_ERROR_IS_OK(werr)) {
9591                 return werr;
9592         }
9593
9594         DEBUG(4,("print processor directory: [%s]\n", path));
9595
9596         r->directory_name = path;
9597
9598         return WERR_OK;
9599 }
9600
9601 /****************************************************************
9602  _spoolss_GetPrintProcessorDirectory
9603 ****************************************************************/
9604
9605 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
9606                                            struct spoolss_GetPrintProcessorDirectory *r)
9607 {
9608         WERROR result;
9609         fstring prnproc_share;
9610         bool prnproc_share_exists = false;
9611         int snum;
9612
9613         /* that's an [in out] buffer */
9614
9615         if (!r->in.buffer && (r->in.offered != 0)) {
9616                 return WERR_INVALID_PARAM;
9617         }
9618
9619         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9620                 r->in.level));
9621
9622         *r->out.needed = 0;
9623
9624         /* r->in.level is ignored */
9625
9626         /* We always should reply with a local print processor directory so that
9627          * users are not forced to have a [prnproc$] share on the Samba spoolss
9628          * server, if users decide to do so, lets announce it though - Guenther */
9629
9630         fstrcpy(prnproc_share, "prnproc$");
9631
9632         snum = find_service(prnproc_share);
9633         if (snum != -1) {
9634                 prnproc_share_exists = true;
9635         }
9636
9637         result = getprintprocessordirectory_level_1(p->mem_ctx,
9638                                                     prnproc_share_exists ? r->in.server : NULL,
9639                                                     r->in.environment,
9640                                                     &r->out.info->info1);
9641         if (!W_ERROR_IS_OK(result)) {
9642                 TALLOC_FREE(r->out.info);
9643                 return result;
9644         }
9645
9646         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
9647                                                                                    r->out.info, r->in.level);
9648         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9649
9650         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9651 }
9652
9653 /*******************************************************************
9654  ********************************************************************/
9655
9656 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9657                                const char *dllname)
9658 {
9659         enum ndr_err_code ndr_err;
9660         struct spoolss_MonitorUi ui;
9661
9662         ui.dll_name = dllname;
9663
9664         ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
9665                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9666         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9667                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9668         }
9669         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9670 }
9671
9672 /*******************************************************************
9673  Streams the monitor UI DLL name in UNICODE
9674 *******************************************************************/
9675
9676 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9677                                struct security_token *token, DATA_BLOB *in,
9678                                DATA_BLOB *out, uint32_t *needed)
9679 {
9680         const char *dllname = "tcpmonui.dll";
9681
9682         *needed = (strlen(dllname)+1) * 2;
9683
9684         if (out->length < *needed) {
9685                 return WERR_INSUFFICIENT_BUFFER;
9686         }
9687
9688         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9689                 return WERR_NOMEM;
9690         }
9691
9692         return WERR_OK;
9693 }
9694
9695 /*******************************************************************
9696  ********************************************************************/
9697
9698 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9699                              struct spoolss_PortData1 *port1,
9700                              const DATA_BLOB *buf)
9701 {
9702         enum ndr_err_code ndr_err;
9703         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
9704                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9705         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9706                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9707         }
9708         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9709 }
9710
9711 /*******************************************************************
9712  ********************************************************************/
9713
9714 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9715                              struct spoolss_PortData2 *port2,
9716                              const DATA_BLOB *buf)
9717 {
9718         enum ndr_err_code ndr_err;
9719         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
9720                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9721         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9722                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9723         }
9724         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9725 }
9726
9727 /*******************************************************************
9728  Create a new TCP/IP port
9729 *******************************************************************/
9730
9731 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9732                              struct security_token *token, DATA_BLOB *in,
9733                              DATA_BLOB *out, uint32_t *needed)
9734 {
9735         struct spoolss_PortData1 port1;
9736         struct spoolss_PortData2 port2;
9737         char *device_uri = NULL;
9738         uint32_t version;
9739
9740         const char *portname;
9741         const char *hostaddress;
9742         const char *queue;
9743         uint32_t port_number;
9744         uint32_t protocol;
9745
9746         /* peek for spoolss_PortData version */
9747
9748         if (!in || (in->length < (128 + 4))) {
9749                 return WERR_GENERAL_FAILURE;
9750         }
9751
9752         version = IVAL(in->data, 128);
9753
9754         switch (version) {
9755                 case 1:
9756                         ZERO_STRUCT(port1);
9757
9758                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
9759                                 return WERR_NOMEM;
9760                         }
9761
9762                         portname        = port1.portname;
9763                         hostaddress     = port1.hostaddress;
9764                         queue           = port1.queue;
9765                         protocol        = port1.protocol;
9766                         port_number     = port1.port_number;
9767
9768                         break;
9769                 case 2:
9770                         ZERO_STRUCT(port2);
9771
9772                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
9773                                 return WERR_NOMEM;
9774                         }
9775
9776                         portname        = port2.portname;
9777                         hostaddress     = port2.hostaddress;
9778                         queue           = port2.queue;
9779                         protocol        = port2.protocol;
9780                         port_number     = port2.port_number;
9781
9782                         break;
9783                 default:
9784                         DEBUG(1,("xcvtcp_addport: "
9785                                 "unknown version of port_data: %d\n", version));
9786                         return WERR_UNKNOWN_PORT;
9787         }
9788
9789         /* create the device URI and call the add_port_hook() */
9790
9791         switch (protocol) {
9792         case PROTOCOL_RAWTCP_TYPE:
9793                 device_uri = talloc_asprintf(mem_ctx,
9794                                 "socket://%s:%d/", hostaddress,
9795                                 port_number);
9796                 break;
9797
9798         case PROTOCOL_LPR_TYPE:
9799                 device_uri = talloc_asprintf(mem_ctx,
9800                         "lpr://%s/%s", hostaddress, queue );
9801                 break;
9802
9803         default:
9804                 return WERR_UNKNOWN_PORT;
9805         }
9806
9807         if (!device_uri) {
9808                 return WERR_NOMEM;
9809         }
9810
9811         return add_port_hook(mem_ctx, token, portname, device_uri);
9812 }
9813
9814 /*******************************************************************
9815 *******************************************************************/
9816
9817 struct xcv_api_table xcvtcp_cmds[] = {
9818         { "MonitorUI",  xcvtcp_monitorui },
9819         { "AddPort",    xcvtcp_addport},
9820         { NULL,         NULL }
9821 };
9822
9823 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9824                                      struct security_token *token, const char *command,
9825                                      DATA_BLOB *inbuf,
9826                                      DATA_BLOB *outbuf,
9827                                      uint32_t *needed )
9828 {
9829         int i;
9830
9831         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9832
9833         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9834                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9835                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9836         }
9837
9838         return WERR_BADFUNC;
9839 }
9840
9841 /*******************************************************************
9842 *******************************************************************/
9843 #if 0   /* don't support management using the "Local Port" monitor */
9844
9845 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9846                                  struct security_token *token, DATA_BLOB *in,
9847                                  DATA_BLOB *out, uint32_t *needed)
9848 {
9849         const char *dllname = "localui.dll";
9850
9851         *needed = (strlen(dllname)+1) * 2;
9852
9853         if (out->length < *needed) {
9854                 return WERR_INSUFFICIENT_BUFFER;
9855         }
9856
9857         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9858                 return WERR_NOMEM;
9859         }
9860
9861         return WERR_OK;
9862 }
9863
9864 /*******************************************************************
9865 *******************************************************************/
9866
9867 struct xcv_api_table xcvlocal_cmds[] = {
9868         { "MonitorUI",  xcvlocal_monitorui },
9869         { NULL,         NULL }
9870 };
9871 #else
9872 struct xcv_api_table xcvlocal_cmds[] = {
9873         { NULL,         NULL }
9874 };
9875 #endif
9876
9877
9878
9879 /*******************************************************************
9880 *******************************************************************/
9881
9882 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9883                                        struct security_token *token, const char *command,
9884                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9885                                        uint32_t *needed)
9886 {
9887         int i;
9888
9889         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9890
9891         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9892                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9893                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9894         }
9895         return WERR_BADFUNC;
9896 }
9897
9898 /****************************************************************
9899  _spoolss_XcvData
9900 ****************************************************************/
9901
9902 WERROR _spoolss_XcvData(struct pipes_struct *p,
9903                         struct spoolss_XcvData *r)
9904 {
9905         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9906         DATA_BLOB out_data = data_blob_null;
9907         WERROR werror;
9908
9909         if (!Printer) {
9910                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9911                         OUR_HANDLE(r->in.handle)));
9912                 return WERR_BADFID;
9913         }
9914
9915         /* Has to be a handle to the TCP/IP port monitor */
9916
9917         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9918                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9919                 return WERR_BADFID;
9920         }
9921
9922         /* requires administrative access to the server */
9923
9924         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9925                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9926                 return WERR_ACCESS_DENIED;
9927         }
9928
9929         /* Allocate the outgoing buffer */
9930
9931         if (r->in.out_data_size) {
9932                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9933                 if (out_data.data == NULL) {
9934                         return WERR_NOMEM;
9935                 }
9936         }
9937
9938         switch ( Printer->printer_type ) {
9939         case SPLHND_PORTMON_TCP:
9940                 werror = process_xcvtcp_command(p->mem_ctx,
9941                                                 p->server_info->ptok,
9942                                                 r->in.function_name,
9943                                                 &r->in.in_data, &out_data,
9944                                                 r->out.needed);
9945                 break;
9946         case SPLHND_PORTMON_LOCAL:
9947                 werror = process_xcvlocal_command(p->mem_ctx,
9948                                                   p->server_info->ptok,
9949                                                   r->in.function_name,
9950                                                   &r->in.in_data, &out_data,
9951                                                   r->out.needed);
9952                 break;
9953         default:
9954                 werror = WERR_INVALID_PRINT_MONITOR;
9955         }
9956
9957         if (!W_ERROR_IS_OK(werror)) {
9958                 return werror;
9959         }
9960
9961         *r->out.status_code = 0;
9962
9963         if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
9964                 memcpy(r->out.out_data, out_data.data,
9965                         MIN(r->in.out_data_size, out_data.length));
9966         }
9967
9968         return WERR_OK;
9969 }
9970
9971 /****************************************************************
9972  _spoolss_AddPrintProcessor
9973 ****************************************************************/
9974
9975 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
9976                                   struct spoolss_AddPrintProcessor *r)
9977 {
9978         /* for now, just indicate success and ignore the add.  We'll
9979            automatically set the winprint processor for printer
9980            entries later.  Used to debug the LexMark Optra S 1855 PCL
9981            driver --jerry */
9982
9983         return WERR_OK;
9984 }
9985
9986 /****************************************************************
9987  _spoolss_AddPort
9988 ****************************************************************/
9989
9990 WERROR _spoolss_AddPort(struct pipes_struct *p,
9991                         struct spoolss_AddPort *r)
9992 {
9993         /* do what w2k3 does */
9994
9995         return WERR_NOT_SUPPORTED;
9996 }
9997
9998 /****************************************************************
9999  _spoolss_GetPrinterDriver
10000 ****************************************************************/
10001
10002 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10003                                  struct spoolss_GetPrinterDriver *r)
10004 {
10005         p->rng_fault_state = true;
10006         return WERR_NOT_SUPPORTED;
10007 }
10008
10009 /****************************************************************
10010  _spoolss_ReadPrinter
10011 ****************************************************************/
10012
10013 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10014                             struct spoolss_ReadPrinter *r)
10015 {
10016         p->rng_fault_state = true;
10017         return WERR_NOT_SUPPORTED;
10018 }
10019
10020 /****************************************************************
10021  _spoolss_WaitForPrinterChange
10022 ****************************************************************/
10023
10024 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10025                                      struct spoolss_WaitForPrinterChange *r)
10026 {
10027         p->rng_fault_state = true;
10028         return WERR_NOT_SUPPORTED;
10029 }
10030
10031 /****************************************************************
10032  _spoolss_ConfigurePort
10033 ****************************************************************/
10034
10035 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10036                               struct spoolss_ConfigurePort *r)
10037 {
10038         p->rng_fault_state = true;
10039         return WERR_NOT_SUPPORTED;
10040 }
10041
10042 /****************************************************************
10043  _spoolss_DeletePort
10044 ****************************************************************/
10045
10046 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10047                            struct spoolss_DeletePort *r)
10048 {
10049         p->rng_fault_state = true;
10050         return WERR_NOT_SUPPORTED;
10051 }
10052
10053 /****************************************************************
10054  _spoolss_CreatePrinterIC
10055 ****************************************************************/
10056
10057 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10058                                 struct spoolss_CreatePrinterIC *r)
10059 {
10060         p->rng_fault_state = true;
10061         return WERR_NOT_SUPPORTED;
10062 }
10063
10064 /****************************************************************
10065  _spoolss_PlayGDIScriptOnPrinterIC
10066 ****************************************************************/
10067
10068 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10069                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
10070 {
10071         p->rng_fault_state = true;
10072         return WERR_NOT_SUPPORTED;
10073 }
10074
10075 /****************************************************************
10076  _spoolss_DeletePrinterIC
10077 ****************************************************************/
10078
10079 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10080                                 struct spoolss_DeletePrinterIC *r)
10081 {
10082         p->rng_fault_state = true;
10083         return WERR_NOT_SUPPORTED;
10084 }
10085
10086 /****************************************************************
10087  _spoolss_AddPrinterConnection
10088 ****************************************************************/
10089
10090 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10091                                      struct spoolss_AddPrinterConnection *r)
10092 {
10093         p->rng_fault_state = true;
10094         return WERR_NOT_SUPPORTED;
10095 }
10096
10097 /****************************************************************
10098  _spoolss_DeletePrinterConnection
10099 ****************************************************************/
10100
10101 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10102                                         struct spoolss_DeletePrinterConnection *r)
10103 {
10104         p->rng_fault_state = true;
10105         return WERR_NOT_SUPPORTED;
10106 }
10107
10108 /****************************************************************
10109  _spoolss_PrinterMessageBox
10110 ****************************************************************/
10111
10112 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10113                                   struct spoolss_PrinterMessageBox *r)
10114 {
10115         p->rng_fault_state = true;
10116         return WERR_NOT_SUPPORTED;
10117 }
10118
10119 /****************************************************************
10120  _spoolss_AddMonitor
10121 ****************************************************************/
10122
10123 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10124                            struct spoolss_AddMonitor *r)
10125 {
10126         p->rng_fault_state = true;
10127         return WERR_NOT_SUPPORTED;
10128 }
10129
10130 /****************************************************************
10131  _spoolss_DeleteMonitor
10132 ****************************************************************/
10133
10134 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10135                               struct spoolss_DeleteMonitor *r)
10136 {
10137         p->rng_fault_state = true;
10138         return WERR_NOT_SUPPORTED;
10139 }
10140
10141 /****************************************************************
10142  _spoolss_DeletePrintProcessor
10143 ****************************************************************/
10144
10145 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10146                                      struct spoolss_DeletePrintProcessor *r)
10147 {
10148         p->rng_fault_state = true;
10149         return WERR_NOT_SUPPORTED;
10150 }
10151
10152 /****************************************************************
10153  _spoolss_AddPrintProvidor
10154 ****************************************************************/
10155
10156 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10157                                  struct spoolss_AddPrintProvidor *r)
10158 {
10159         p->rng_fault_state = true;
10160         return WERR_NOT_SUPPORTED;
10161 }
10162
10163 /****************************************************************
10164  _spoolss_DeletePrintProvidor
10165 ****************************************************************/
10166
10167 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10168                                     struct spoolss_DeletePrintProvidor *r)
10169 {
10170         p->rng_fault_state = true;
10171         return WERR_NOT_SUPPORTED;
10172 }
10173
10174 /****************************************************************
10175  _spoolss_FindFirstPrinterChangeNotification
10176 ****************************************************************/
10177
10178 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10179                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
10180 {
10181         p->rng_fault_state = true;
10182         return WERR_NOT_SUPPORTED;
10183 }
10184
10185 /****************************************************************
10186  _spoolss_FindNextPrinterChangeNotification
10187 ****************************************************************/
10188
10189 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10190                                                   struct spoolss_FindNextPrinterChangeNotification *r)
10191 {
10192         p->rng_fault_state = true;
10193         return WERR_NOT_SUPPORTED;
10194 }
10195
10196 /****************************************************************
10197  _spoolss_RouterFindFirstPrinterChangeNotificationOld
10198 ****************************************************************/
10199
10200 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10201                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10202 {
10203         p->rng_fault_state = true;
10204         return WERR_NOT_SUPPORTED;
10205 }
10206
10207 /****************************************************************
10208  _spoolss_ReplyOpenPrinter
10209 ****************************************************************/
10210
10211 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10212                                  struct spoolss_ReplyOpenPrinter *r)
10213 {
10214         p->rng_fault_state = true;
10215         return WERR_NOT_SUPPORTED;
10216 }
10217
10218 /****************************************************************
10219  _spoolss_RouterReplyPrinter
10220 ****************************************************************/
10221
10222 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10223                                    struct spoolss_RouterReplyPrinter *r)
10224 {
10225         p->rng_fault_state = true;
10226         return WERR_NOT_SUPPORTED;
10227 }
10228
10229 /****************************************************************
10230  _spoolss_ReplyClosePrinter
10231 ****************************************************************/
10232
10233 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10234                                   struct spoolss_ReplyClosePrinter *r)
10235 {
10236         p->rng_fault_state = true;
10237         return WERR_NOT_SUPPORTED;
10238 }
10239
10240 /****************************************************************
10241  _spoolss_AddPortEx
10242 ****************************************************************/
10243
10244 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10245                           struct spoolss_AddPortEx *r)
10246 {
10247         p->rng_fault_state = true;
10248         return WERR_NOT_SUPPORTED;
10249 }
10250
10251 /****************************************************************
10252  _spoolss_RouterFindFirstPrinterChangeNotification
10253 ****************************************************************/
10254
10255 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10256                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10257 {
10258         p->rng_fault_state = true;
10259         return WERR_NOT_SUPPORTED;
10260 }
10261
10262 /****************************************************************
10263  _spoolss_SpoolerInit
10264 ****************************************************************/
10265
10266 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10267                             struct spoolss_SpoolerInit *r)
10268 {
10269         p->rng_fault_state = true;
10270         return WERR_NOT_SUPPORTED;
10271 }
10272
10273 /****************************************************************
10274  _spoolss_ResetPrinterEx
10275 ****************************************************************/
10276
10277 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10278                                struct spoolss_ResetPrinterEx *r)
10279 {
10280         p->rng_fault_state = true;
10281         return WERR_NOT_SUPPORTED;
10282 }
10283
10284 /****************************************************************
10285  _spoolss_RouterReplyPrinterEx
10286 ****************************************************************/
10287
10288 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10289                                      struct spoolss_RouterReplyPrinterEx *r)
10290 {
10291         p->rng_fault_state = true;
10292         return WERR_NOT_SUPPORTED;
10293 }
10294
10295 /****************************************************************
10296  _spoolss_44
10297 ****************************************************************/
10298
10299 WERROR _spoolss_44(struct pipes_struct *p,
10300                    struct spoolss_44 *r)
10301 {
10302         p->rng_fault_state = true;
10303         return WERR_NOT_SUPPORTED;
10304 }
10305
10306 /****************************************************************
10307  _spoolss_SetPort
10308 ****************************************************************/
10309
10310 WERROR _spoolss_SetPort(struct pipes_struct *p,
10311                         struct spoolss_SetPort *r)
10312 {
10313         p->rng_fault_state = true;
10314         return WERR_NOT_SUPPORTED;
10315 }
10316
10317 /****************************************************************
10318  _spoolss_4a
10319 ****************************************************************/
10320
10321 WERROR _spoolss_4a(struct pipes_struct *p,
10322                    struct spoolss_4a *r)
10323 {
10324         p->rng_fault_state = true;
10325         return WERR_NOT_SUPPORTED;
10326 }
10327
10328 /****************************************************************
10329  _spoolss_4b
10330 ****************************************************************/
10331
10332 WERROR _spoolss_4b(struct pipes_struct *p,
10333                    struct spoolss_4b *r)
10334 {
10335         p->rng_fault_state = true;
10336         return WERR_NOT_SUPPORTED;
10337 }
10338
10339 /****************************************************************
10340  _spoolss_4c
10341 ****************************************************************/
10342
10343 WERROR _spoolss_4c(struct pipes_struct *p,
10344                    struct spoolss_4c *r)
10345 {
10346         p->rng_fault_state = true;
10347         return WERR_NOT_SUPPORTED;
10348 }
10349
10350 /****************************************************************
10351  _spoolss_53
10352 ****************************************************************/
10353
10354 WERROR _spoolss_53(struct pipes_struct *p,
10355                    struct spoolss_53 *r)
10356 {
10357         p->rng_fault_state = true;
10358         return WERR_NOT_SUPPORTED;
10359 }
10360
10361 /****************************************************************
10362  _spoolss_55
10363 ****************************************************************/
10364
10365 WERROR _spoolss_55(struct pipes_struct *p,
10366                    struct spoolss_55 *r)
10367 {
10368         p->rng_fault_state = true;
10369         return WERR_NOT_SUPPORTED;
10370 }
10371
10372 /****************************************************************
10373  _spoolss_56
10374 ****************************************************************/
10375
10376 WERROR _spoolss_56(struct pipes_struct *p,
10377                    struct spoolss_56 *r)
10378 {
10379         p->rng_fault_state = true;
10380         return WERR_NOT_SUPPORTED;
10381 }
10382
10383 /****************************************************************
10384  _spoolss_57
10385 ****************************************************************/
10386
10387 WERROR _spoolss_57(struct pipes_struct *p,
10388                    struct spoolss_57 *r)
10389 {
10390         p->rng_fault_state = true;
10391         return WERR_NOT_SUPPORTED;
10392 }
10393
10394 /****************************************************************
10395  _spoolss_5a
10396 ****************************************************************/
10397
10398 WERROR _spoolss_5a(struct pipes_struct *p,
10399                    struct spoolss_5a *r)
10400 {
10401         p->rng_fault_state = true;
10402         return WERR_NOT_SUPPORTED;
10403 }
10404
10405 /****************************************************************
10406  _spoolss_5b
10407 ****************************************************************/
10408
10409 WERROR _spoolss_5b(struct pipes_struct *p,
10410                    struct spoolss_5b *r)
10411 {
10412         p->rng_fault_state = true;
10413         return WERR_NOT_SUPPORTED;
10414 }
10415
10416 /****************************************************************
10417  _spoolss_5c
10418 ****************************************************************/
10419
10420 WERROR _spoolss_5c(struct pipes_struct *p,
10421                    struct spoolss_5c *r)
10422 {
10423         p->rng_fault_state = true;
10424         return WERR_NOT_SUPPORTED;
10425 }
10426
10427 /****************************************************************
10428  _spoolss_5d
10429 ****************************************************************/
10430
10431 WERROR _spoolss_5d(struct pipes_struct *p,
10432                    struct spoolss_5d *r)
10433 {
10434         p->rng_fault_state = true;
10435         return WERR_NOT_SUPPORTED;
10436 }
10437
10438 /****************************************************************
10439  _spoolss_5e
10440 ****************************************************************/
10441
10442 WERROR _spoolss_5e(struct pipes_struct *p,
10443                    struct spoolss_5e *r)
10444 {
10445         p->rng_fault_state = true;
10446         return WERR_NOT_SUPPORTED;
10447 }
10448
10449 /****************************************************************
10450  _spoolss_5f
10451 ****************************************************************/
10452
10453 WERROR _spoolss_5f(struct pipes_struct *p,
10454                    struct spoolss_5f *r)
10455 {
10456         p->rng_fault_state = true;
10457         return WERR_NOT_SUPPORTED;
10458 }
10459
10460 /****************************************************************
10461  _spoolss_60
10462 ****************************************************************/
10463
10464 WERROR _spoolss_60(struct pipes_struct *p,
10465                    struct spoolss_60 *r)
10466 {
10467         p->rng_fault_state = true;
10468         return WERR_NOT_SUPPORTED;
10469 }
10470
10471 /****************************************************************
10472  _spoolss_61
10473 ****************************************************************/
10474
10475 WERROR _spoolss_61(struct pipes_struct *p,
10476                    struct spoolss_61 *r)
10477 {
10478         p->rng_fault_state = true;
10479         return WERR_NOT_SUPPORTED;
10480 }
10481
10482 /****************************************************************
10483  _spoolss_62
10484 ****************************************************************/
10485
10486 WERROR _spoolss_62(struct pipes_struct *p,
10487                    struct spoolss_62 *r)
10488 {
10489         p->rng_fault_state = true;
10490         return WERR_NOT_SUPPORTED;
10491 }
10492
10493 /****************************************************************
10494  _spoolss_63
10495 ****************************************************************/
10496
10497 WERROR _spoolss_63(struct pipes_struct *p,
10498                    struct spoolss_63 *r)
10499 {
10500         p->rng_fault_state = true;
10501         return WERR_NOT_SUPPORTED;
10502 }
10503
10504 /****************************************************************
10505  _spoolss_64
10506 ****************************************************************/
10507
10508 WERROR _spoolss_64(struct pipes_struct *p,
10509                    struct spoolss_64 *r)
10510 {
10511         p->rng_fault_state = true;
10512         return WERR_NOT_SUPPORTED;
10513 }
10514
10515 /****************************************************************
10516  _spoolss_65
10517 ****************************************************************/
10518
10519 WERROR _spoolss_65(struct pipes_struct *p,
10520                    struct spoolss_65 *r)
10521 {
10522         p->rng_fault_state = true;
10523         return WERR_NOT_SUPPORTED;
10524 }
10525
10526 /****************************************************************
10527  _spoolss_GetCorePrinterDrivers
10528 ****************************************************************/
10529
10530 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
10531                                       struct spoolss_GetCorePrinterDrivers *r)
10532 {
10533         p->rng_fault_state = true;
10534         return WERR_NOT_SUPPORTED;
10535 }
10536
10537 /****************************************************************
10538  _spoolss_67
10539 ****************************************************************/
10540
10541 WERROR _spoolss_67(struct pipes_struct *p,
10542                    struct spoolss_67 *r)
10543 {
10544         p->rng_fault_state = true;
10545         return WERR_NOT_SUPPORTED;
10546 }
10547
10548 /****************************************************************
10549  _spoolss_GetPrinterDriverPackagePath
10550 ****************************************************************/
10551
10552 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
10553                                             struct spoolss_GetPrinterDriverPackagePath *r)
10554 {
10555         p->rng_fault_state = true;
10556         return WERR_NOT_SUPPORTED;
10557 }
10558
10559 /****************************************************************
10560  _spoolss_69
10561 ****************************************************************/
10562
10563 WERROR _spoolss_69(struct pipes_struct *p,
10564                    struct spoolss_69 *r)
10565 {
10566         p->rng_fault_state = true;
10567         return WERR_NOT_SUPPORTED;
10568 }
10569
10570 /****************************************************************
10571  _spoolss_6a
10572 ****************************************************************/
10573
10574 WERROR _spoolss_6a(struct pipes_struct *p,
10575                    struct spoolss_6a *r)
10576 {
10577         p->rng_fault_state = true;
10578         return WERR_NOT_SUPPORTED;
10579 }
10580
10581 /****************************************************************
10582  _spoolss_6b
10583 ****************************************************************/
10584
10585 WERROR _spoolss_6b(struct pipes_struct *p,
10586                    struct spoolss_6b *r)
10587 {
10588         p->rng_fault_state = true;
10589         return WERR_NOT_SUPPORTED;
10590 }
10591
10592 /****************************************************************
10593  _spoolss_6c
10594 ****************************************************************/
10595
10596 WERROR _spoolss_6c(struct pipes_struct *p,
10597                    struct spoolss_6c *r)
10598 {
10599         p->rng_fault_state = true;
10600         return WERR_NOT_SUPPORTED;
10601 }
10602
10603 /****************************************************************
10604  _spoolss_6d
10605 ****************************************************************/
10606
10607 WERROR _spoolss_6d(struct pipes_struct *p,
10608                    struct spoolss_6d *r)
10609 {
10610         p->rng_fault_state = true;
10611         return WERR_NOT_SUPPORTED;
10612 }