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