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