s3-server_id: only include server_id where needed.
[ab/samba.git/.git] / source3 / rpc_server / spoolss / 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/ndr_spoolss_c.h"
35 #include "rpc_client/init_spoolss.h"
36 #include "rpc_client/cli_pipe.h"
37 #include "librpc/gen_ndr/messaging.h"
38 #include "../libcli/security/security.h"
39 #include "librpc/gen_ndr/ndr_security.h"
40 #include "registry.h"
41 #include "registry/reg_objects.h"
42 #include "include/printing.h"
43 #include "secrets.h"
44 #include "../librpc/gen_ndr/netlogon.h"
45 #include "rpc_misc.h"
46 #include "printing/notify.h"
47 #include "serverid.h"
48
49 /* macros stolen from s4 spoolss server */
50 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
51         ((info)?ndr_size_##fn(info, level, 0):0)
52
53 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
54         ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
55
56 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
57         ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
58
59 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
60
61 #undef DBGC_CLASS
62 #define DBGC_CLASS DBGC_RPC_SRV
63
64 #ifndef MAX_OPEN_PRINTER_EXS
65 #define MAX_OPEN_PRINTER_EXS 50
66 #endif
67
68 struct notify_back_channel;
69
70 /* structure to store the printer handles */
71 /* and a reference to what it's pointing to */
72 /* and the notify info asked about */
73 /* that's the central struct */
74 struct printer_handle {
75         struct printer_handle *prev, *next;
76         bool document_started;
77         bool page_started;
78         uint32 jobid; /* jobid in printing backend */
79         int printer_type;
80         const char *servername;
81         fstring sharename;
82         uint32 type;
83         uint32 access_granted;
84         struct {
85                 uint32 flags;
86                 uint32 options;
87                 fstring localmachine;
88                 uint32 printerlocal;
89                 struct spoolss_NotifyOption *option;
90                 struct policy_handle cli_hnd;
91                 struct notify_back_channel *cli_chan;
92                 uint32 change;
93                 /* are we in a FindNextPrinterChangeNotify() call? */
94                 bool fnpcn;
95                 struct messaging_context *msg_ctx;
96         } notify;
97         struct {
98                 fstring machine;
99                 fstring user;
100         } client;
101
102         /* devmode sent in the OpenPrinter() call */
103         struct spoolss_DeviceMode *devmode;
104
105         /* TODO cache the printer info2 structure */
106         struct spoolss_PrinterInfo2 *info2;
107
108 };
109
110 static struct printer_handle *printers_list;
111
112 struct printer_session_counter {
113         struct printer_session_counter *next;
114         struct printer_session_counter *prev;
115
116         int snum;
117         uint32_t counter;
118 };
119
120 static struct printer_session_counter *counter_list;
121
122 struct notify_back_channel {
123         struct notify_back_channel *prev, *next;
124
125         /* associated client */
126         struct sockaddr_storage client_address;
127
128         /* print notify back-channel pipe handle*/
129         struct rpc_pipe_client *cli_pipe;
130         struct dcerpc_binding_handle *binding_handle;
131         uint32_t active_connections;
132 };
133
134 static struct notify_back_channel *back_channels;
135
136 /* Map generic permissions to printer object specific permissions */
137
138 const struct standard_mapping printer_std_mapping = {
139         PRINTER_READ,
140         PRINTER_WRITE,
141         PRINTER_EXECUTE,
142         PRINTER_ALL_ACCESS
143 };
144
145 /* Map generic permissions to print server object specific permissions */
146
147 const struct standard_mapping printserver_std_mapping = {
148         SERVER_READ,
149         SERVER_WRITE,
150         SERVER_EXECUTE,
151         SERVER_ALL_ACCESS
152 };
153
154 /* API table for Xcv Monitor functions */
155
156 struct xcv_api_table {
157         const char *name;
158         WERROR(*fn) (TALLOC_CTX *mem_ctx, struct security_token *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
159 };
160
161 static void prune_printername_cache(void);
162
163 /********************************************************************
164  * Canonicalize servername.
165  ********************************************************************/
166
167 static const char *canon_servername(const char *servername)
168 {
169         const char *pservername = servername;
170         while (*pservername == '\\') {
171                 pservername++;
172         }
173         return pservername;
174 }
175
176 /* translate between internal status numbers and NT status numbers */
177 static int nt_printj_status(int v)
178 {
179         switch (v) {
180         case LPQ_QUEUED:
181                 return 0;
182         case LPQ_PAUSED:
183                 return JOB_STATUS_PAUSED;
184         case LPQ_SPOOLING:
185                 return JOB_STATUS_SPOOLING;
186         case LPQ_PRINTING:
187                 return JOB_STATUS_PRINTING;
188         case LPQ_ERROR:
189                 return JOB_STATUS_ERROR;
190         case LPQ_DELETING:
191                 return JOB_STATUS_DELETING;
192         case LPQ_OFFLINE:
193                 return JOB_STATUS_OFFLINE;
194         case LPQ_PAPEROUT:
195                 return JOB_STATUS_PAPEROUT;
196         case LPQ_PRINTED:
197                 return JOB_STATUS_PRINTED;
198         case LPQ_DELETED:
199                 return JOB_STATUS_DELETED;
200         case LPQ_BLOCKED:
201                 return JOB_STATUS_BLOCKED_DEVQ;
202         case LPQ_USER_INTERVENTION:
203                 return JOB_STATUS_USER_INTERVENTION;
204         }
205         return 0;
206 }
207
208 static int nt_printq_status(int v)
209 {
210         switch (v) {
211         case LPQ_PAUSED:
212                 return PRINTER_STATUS_PAUSED;
213         case LPQ_QUEUED:
214         case LPQ_SPOOLING:
215         case LPQ_PRINTING:
216                 return 0;
217         }
218         return 0;
219 }
220
221 /***************************************************************************
222  Disconnect from the client
223 ****************************************************************************/
224
225 static void srv_spoolss_replycloseprinter(int snum,
226                                           struct printer_handle *prn_hnd)
227 {
228         WERROR result;
229         NTSTATUS status;
230
231         /*
232          * Tell the specific printing tdb we no longer want messages for this printer
233          * by deregistering our PID.
234          */
235
236         if (!print_notify_deregister_pid(snum)) {
237                 DEBUG(0, ("Failed to register our pid for printer %s\n",
238                           lp_const_servicename(snum)));
239         }
240
241         /* weird if the test succeeds !!! */
242         if (prn_hnd->notify.cli_chan == NULL ||
243             prn_hnd->notify.cli_chan->active_connections == 0) {
244                 DEBUG(0, ("Trying to close unexisting backchannel!\n"));
245                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
246                 TALLOC_FREE(prn_hnd->notify.cli_chan);
247                 return;
248         }
249
250         status = dcerpc_spoolss_ReplyClosePrinter(
251                                         prn_hnd->notify.cli_chan->binding_handle,
252                                         talloc_tos(),
253                                         &prn_hnd->notify.cli_hnd,
254                                         &result);
255         if (!NT_STATUS_IS_OK(status)) {
256                 DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
257                           nt_errstr(status)));
258                 result = ntstatus_to_werror(status);
259         } else if (!W_ERROR_IS_OK(result)) {
260                 DEBUG(0, ("reply_close_printer failed [%s].\n",
261                           win_errstr(result)));
262         }
263
264         /* if it's the last connection, deconnect the IPC$ share */
265         if (prn_hnd->notify.cli_chan->active_connections == 1) {
266
267                 prn_hnd->notify.cli_chan->binding_handle = NULL;
268                 cli_shutdown(rpc_pipe_np_smb_conn(prn_hnd->notify.cli_chan->cli_pipe));
269                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
270                 TALLOC_FREE(prn_hnd->notify.cli_chan);
271
272                 if (prn_hnd->notify.msg_ctx != NULL) {
273                         messaging_deregister(prn_hnd->notify.msg_ctx,
274                                              MSG_PRINTER_NOTIFY2, NULL);
275
276                         /*
277                          * Tell the serverid.tdb we're no longer
278                          * interested in printer notify messages.
279                          */
280
281                         serverid_register_msg_flags(
282                                 messaging_server_id(prn_hnd->notify.msg_ctx),
283                                 false, FLAG_MSG_PRINT_NOTIFY);
284                 }
285         }
286
287         if (prn_hnd->notify.cli_chan) {
288                 prn_hnd->notify.cli_chan->active_connections--;
289         }
290 }
291
292 /****************************************************************************
293  Functions to free a printer entry datastruct.
294 ****************************************************************************/
295
296 static int printer_entry_destructor(struct printer_handle *Printer)
297 {
298         if (Printer->notify.cli_chan != NULL &&
299             Printer->notify.cli_chan->active_connections > 0) {
300                 int snum = -1;
301
302                 switch(Printer->printer_type) {
303                 case SPLHND_SERVER:
304                         srv_spoolss_replycloseprinter(snum, Printer);
305                         break;
306
307                 case SPLHND_PRINTER:
308                         snum = print_queue_snum(Printer->sharename);
309                         if (snum != -1) {
310                                 srv_spoolss_replycloseprinter(snum, Printer);
311                         }
312                         break;
313                 default:
314                         break;
315                 }
316         }
317
318         Printer->notify.flags=0;
319         Printer->notify.options=0;
320         Printer->notify.localmachine[0]='\0';
321         Printer->notify.printerlocal=0;
322         TALLOC_FREE(Printer->notify.option);
323         TALLOC_FREE(Printer->devmode);
324
325         /* Remove from the internal list. */
326         DLIST_REMOVE(printers_list, Printer);
327         return 0;
328 }
329
330 /****************************************************************************
331   find printer index by handle
332 ****************************************************************************/
333
334 static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
335                                                         struct policy_handle *hnd)
336 {
337         struct printer_handle *find_printer = NULL;
338
339         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
340                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
341                 return NULL;
342         }
343
344         return find_printer;
345 }
346
347 /****************************************************************************
348  Close printer index by handle.
349 ****************************************************************************/
350
351 static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
352 {
353         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
354
355         if (!Printer) {
356                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
357                         OUR_HANDLE(hnd)));
358                 return false;
359         }
360
361         close_policy_hnd(p, hnd);
362
363         return true;
364 }
365
366 /****************************************************************************
367  Delete a printer given a handle.
368 ****************************************************************************/
369
370 static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
371                                   const char *sharename,
372                                   struct messaging_context *msg_ctx)
373 {
374         char *cmd = lp_deleteprinter_cmd();
375         char *command = NULL;
376         int ret;
377         bool is_print_op = false;
378
379         /* can't fail if we don't try */
380
381         if ( !*cmd )
382                 return WERR_OK;
383
384         command = talloc_asprintf(ctx,
385                         "%s \"%s\"",
386                         cmd, sharename);
387         if (!command) {
388                 return WERR_NOMEM;
389         }
390         if ( token )
391                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
392
393         DEBUG(10,("Running [%s]\n", command));
394
395         /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
396
397         if ( is_print_op )
398                 become_root();
399
400         if ( (ret = smbrun(command, NULL)) == 0 ) {
401                 /* Tell everyone we updated smb.conf. */
402                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
403         }
404
405         if ( is_print_op )
406                 unbecome_root();
407
408         /********** END SePrintOperatorPrivlege BLOCK **********/
409
410         DEBUGADD(10,("returned [%d]\n", ret));
411
412         TALLOC_FREE(command);
413
414         if (ret != 0)
415                 return WERR_BADFID; /* What to return here? */
416
417         /* go ahead and re-read the services immediately */
418         become_root();
419         reload_services(msg_ctx, -1, false);
420         unbecome_root();
421
422         if ( lp_servicenumber( sharename ) >= 0 )
423                 return WERR_ACCESS_DENIED;
424
425         return WERR_OK;
426 }
427
428 /****************************************************************************
429  Delete a printer given a handle.
430 ****************************************************************************/
431
432 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
433 {
434         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
435         WERROR result;
436
437         if (!Printer) {
438                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
439                         OUR_HANDLE(hnd)));
440                 return WERR_BADFID;
441         }
442
443         /*
444          * It turns out that Windows allows delete printer on a handle
445          * opened by an admin user, then used on a pipe handle created
446          * by an anonymous user..... but they're working on security.... riiight !
447          * JRA.
448          */
449
450         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
451                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
452                 return WERR_ACCESS_DENIED;
453         }
454
455         /* this does not need a become root since the access check has been
456            done on the handle already */
457
458         result = winreg_delete_printer_key(p->mem_ctx,
459                                            get_session_info_system(),
460                                            p->msg_ctx,
461                                            Printer->sharename,
462                                            "");
463         if (!W_ERROR_IS_OK(result)) {
464                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
465                 return WERR_BADFID;
466         }
467
468         result = delete_printer_hook(p->mem_ctx, p->session_info->security_token,
469                                      Printer->sharename, p->msg_ctx);
470         if (!W_ERROR_IS_OK(result)) {
471                 return result;
472         }
473         prune_printername_cache();
474         return WERR_OK;
475 }
476
477 /****************************************************************************
478  Return the snum of a printer corresponding to an handle.
479 ****************************************************************************/
480
481 static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
482                              int *number, struct share_params **params)
483 {
484         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
485
486         if (!Printer) {
487                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
488                         OUR_HANDLE(hnd)));
489                 return false;
490         }
491
492         switch (Printer->printer_type) {
493                 case SPLHND_PRINTER:
494                         DEBUG(4,("short name:%s\n", Printer->sharename));
495                         *number = print_queue_snum(Printer->sharename);
496                         return (*number != -1);
497                 case SPLHND_SERVER:
498                         return false;
499                 default:
500                         return false;
501         }
502 }
503
504 /****************************************************************************
505  Set printer handle type.
506  Check if it's \\server or \\server\printer
507 ****************************************************************************/
508
509 static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
510 {
511         DEBUG(3,("Setting printer type=%s\n", handlename));
512
513         /* it's a print server */
514         if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
515                 DEBUGADD(4,("Printer is a print server\n"));
516                 Printer->printer_type = SPLHND_SERVER;
517         }
518         /* it's a printer (set_printer_hnd_name() will handle port monitors */
519         else {
520                 DEBUGADD(4,("Printer is a printer\n"));
521                 Printer->printer_type = SPLHND_PRINTER;
522         }
523
524         return true;
525 }
526
527 static void prune_printername_cache_fn(const char *key, const char *value,
528                                        time_t timeout, void *private_data)
529 {
530         gencache_del(key);
531 }
532
533 static void prune_printername_cache(void)
534 {
535         gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
536 }
537
538 /****************************************************************************
539  Set printer handle name..  Accept names like \\server, \\server\printer,
540  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
541  the MSDN docs regarding OpenPrinter() for details on the XcvData() and
542  XcvDataPort() interface.
543 ****************************************************************************/
544
545 static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
546                                    const struct auth_serversupplied_info *session_info,
547                                    struct messaging_context *msg_ctx,
548                                    struct printer_handle *Printer,
549                                    const char *handlename)
550 {
551         int snum;
552         int n_services=lp_numservices();
553         char *aprinter;
554         const char *printername;
555         const char *servername = NULL;
556         fstring sname;
557         bool found = false;
558         struct spoolss_PrinterInfo2 *info2 = NULL;
559         WERROR result;
560         char *p;
561
562         /*
563          * Hopefully nobody names his printers like this. Maybe \ or ,
564          * are illegal in printer names even?
565          */
566         const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
567         char *cache_key;
568         char *tmp;
569
570         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
571                 (unsigned long)strlen(handlename)));
572
573         aprinter = CONST_DISCARD(char *, handlename);
574         if ( *handlename == '\\' ) {
575                 servername = canon_servername(handlename);
576                 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
577                         *aprinter = '\0';
578                         aprinter++;
579                 }
580                 if (!is_myname_or_ipaddr(servername)) {
581                         return WERR_INVALID_PRINTER_NAME;
582                 }
583                 Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
584                 if (Printer->servername == NULL) {
585                         return WERR_NOMEM;
586                 }
587         }
588
589         if (Printer->printer_type == SPLHND_SERVER) {
590                 return WERR_OK;
591         }
592
593         if (Printer->printer_type != SPLHND_PRINTER) {
594                 return WERR_INVALID_HANDLE;
595         }
596
597         DEBUGADD(5, ("searching for [%s]\n", aprinter));
598
599         p = strchr(aprinter, ',');
600         if (p != NULL) {
601                 char *p2 = p;
602                 p++;
603                 if (*p == ' ') {
604                         p++;
605                 }
606                 if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
607                         *p2 = '\0';
608                 } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
609                         *p2 = '\0';
610                 }
611         }
612
613         if (p) {
614                 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
615         }
616
617         /* check for the Port Monitor Interface */
618         if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
619                 Printer->printer_type = SPLHND_PORTMON_TCP;
620                 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
621                 found = true;
622         }
623         else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
624                 Printer->printer_type = SPLHND_PORTMON_LOCAL;
625                 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
626                 found = true;
627         }
628
629         /*
630          * With hundreds of printers, the "for" loop iterating all
631          * shares can be quite expensive, as it is done on every
632          * OpenPrinter. The loop maps "aprinter" to "sname", the
633          * result of which we cache in gencache.
634          */
635
636         cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s",
637                                     aprinter);
638         if ((cache_key != NULL) && gencache_get(cache_key, &tmp, NULL)) {
639
640                 found = (strcmp(tmp, printer_not_found) != 0);
641                 if (!found) {
642                         DEBUG(4, ("Printer %s not found\n", aprinter));
643                         SAFE_FREE(tmp);
644                         return WERR_INVALID_PRINTER_NAME;
645                 }
646                 fstrcpy(sname, tmp);
647                 SAFE_FREE(tmp);
648         }
649
650         /* Search all sharenames first as this is easier than pulling
651            the printer_info_2 off of disk. Don't use find_service() since
652            that calls out to map_username() */
653
654         /* do another loop to look for printernames */
655         for (snum = 0; !found && snum < n_services; snum++) {
656                 const char *printer = lp_const_servicename(snum);
657
658                 /* no point going on if this is not a printer */
659                 if (!(lp_snum_ok(snum) && lp_print_ok(snum))) {
660                         continue;
661                 }
662
663                 /* ignore [printers] share */
664                 if (strequal(printer, "printers")) {
665                         continue;
666                 }
667
668                 fstrcpy(sname, printer);
669                 if (strequal(aprinter, printer)) {
670                         found = true;
671                         break;
672                 }
673
674                 /* no point looking up the printer object if
675                    we aren't allowing printername != sharename */
676                 if (lp_force_printername(snum)) {
677                         continue;
678                 }
679
680                 result = winreg_get_printer(mem_ctx,
681                                             session_info,
682                                             msg_ctx,
683                                             sname,
684                                             &info2);
685                 if ( !W_ERROR_IS_OK(result) ) {
686                         DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
687                                  sname, win_errstr(result)));
688                         continue;
689                 }
690
691                 printername = strrchr(info2->printername, '\\');
692                 if (printername == NULL) {
693                         printername = info2->printername;
694                 } else {
695                         printername++;
696                 }
697
698                 if (strequal(printername, aprinter)) {
699                         found = true;
700                         break;
701                 }
702
703                 DEBUGADD(10, ("printername: %s\n", printername));
704
705                 TALLOC_FREE(info2);
706         }
707
708         if ( !found ) {
709                 if (cache_key != NULL) {
710                         gencache_set(cache_key, printer_not_found,
711                                      time(NULL)+300);
712                         TALLOC_FREE(cache_key);
713                 }
714                 DEBUGADD(4,("Printer not found\n"));
715                 return WERR_INVALID_PRINTER_NAME;
716         }
717
718         if (cache_key != NULL) {
719                 gencache_set(cache_key, sname, time(NULL)+300);
720                 TALLOC_FREE(cache_key);
721         }
722
723         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
724
725         fstrcpy(Printer->sharename, sname);
726
727         return WERR_OK;
728 }
729
730 /****************************************************************************
731  Find first available printer slot. creates a printer handle for you.
732  ****************************************************************************/
733
734 static WERROR open_printer_hnd(struct pipes_struct *p,
735                                struct policy_handle *hnd,
736                                const char *name,
737                                uint32_t access_granted)
738 {
739         struct printer_handle *new_printer;
740         WERROR result;
741
742         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
743
744         new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
745         if (new_printer == NULL) {
746                 return WERR_NOMEM;
747         }
748         talloc_set_destructor(new_printer, printer_entry_destructor);
749
750         /* This also steals the printer_handle on the policy_handle */
751         if (!create_policy_hnd(p, hnd, new_printer)) {
752                 TALLOC_FREE(new_printer);
753                 return WERR_INVALID_HANDLE;
754         }
755
756         /* Add to the internal list. */
757         DLIST_ADD(printers_list, new_printer);
758
759         new_printer->notify.option=NULL;
760
761         if (!set_printer_hnd_printertype(new_printer, name)) {
762                 close_printer_handle(p, hnd);
763                 return WERR_INVALID_HANDLE;
764         }
765
766         result = set_printer_hnd_name(p->mem_ctx,
767                                       get_session_info_system(),
768                                       p->msg_ctx,
769                                       new_printer, name);
770         if (!W_ERROR_IS_OK(result)) {
771                 close_printer_handle(p, hnd);
772                 return result;
773         }
774
775         new_printer->access_granted = access_granted;
776
777         DEBUG(5, ("%d printer handles active\n",
778                   (int)num_pipe_handles(p)));
779
780         return WERR_OK;
781 }
782
783 /***************************************************************************
784  check to see if the client motify handle is monitoring the notification
785  given by (notify_type, notify_field).
786  **************************************************************************/
787
788 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
789                                       uint16_t notify_field)
790 {
791         return true;
792 }
793
794 static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
795                                 uint16_t notify_field)
796 {
797         struct spoolss_NotifyOption *option = p->notify.option;
798         uint32_t i, j;
799
800         /*
801          * Flags should always be zero when the change notify
802          * is registered by the client's spooler.  A user Win32 app
803          * might use the flags though instead of the NOTIFY_OPTION_INFO
804          * --jerry
805          */
806
807         if (!option) {
808                 return false;
809         }
810
811         if (p->notify.flags)
812                 return is_monitoring_event_flags(
813                         p->notify.flags, notify_type, notify_field);
814
815         for (i = 0; i < option->count; i++) {
816
817                 /* Check match for notify_type */
818
819                 if (option->types[i].type != notify_type)
820                         continue;
821
822                 /* Check match for field */
823
824                 for (j = 0; j < option->types[i].count; j++) {
825                         if (option->types[i].fields[j].field == notify_field) {
826                                 return true;
827                         }
828                 }
829         }
830
831         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
832                    p->servername, p->sharename, notify_type, notify_field));
833
834         return false;
835 }
836
837 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
838         _data->data.integer[0] = _integer; \
839         _data->data.integer[1] = 0;
840
841
842 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
843         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
844         if (!_data->data.string.string) {\
845                 _data->data.string.size = 0; \
846         } \
847         _data->data.string.size = strlen_m_term(_p) * 2;
848
849 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
850         _data->data.devmode.devmode = _devmode;
851
852 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
853         _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
854         if (!_data->data.sd.sd) { \
855                 _data->data.sd.sd_size = 0; \
856         } \
857         _data->data.sd.sd_size = \
858                 ndr_size_security_descriptor(_data->data.sd.sd, 0);
859
860 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
861                                    struct tm *t,
862                                    const char **pp,
863                                    uint32_t *plen)
864 {
865         struct spoolss_Time st;
866         uint32_t len = 16;
867         char *p;
868
869         if (!init_systemtime(&st, t)) {
870                 return;
871         }
872
873         p = talloc_array(mem_ctx, char, len);
874         if (!p) {
875                 return;
876         }
877
878         /*
879          * Systemtime must be linearized as a set of UINT16's.
880          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
881          */
882
883         SSVAL(p, 0, st.year);
884         SSVAL(p, 2, st.month);
885         SSVAL(p, 4, st.day_of_week);
886         SSVAL(p, 6, st.day);
887         SSVAL(p, 8, st.hour);
888         SSVAL(p, 10, st.minute);
889         SSVAL(p, 12, st.second);
890         SSVAL(p, 14, st.millisecond);
891
892         *pp = p;
893         *plen = len;
894 }
895
896 /* Convert a notification message to a struct spoolss_Notify */
897
898 static void notify_one_value(struct spoolss_notify_msg *msg,
899                              struct spoolss_Notify *data,
900                              TALLOC_CTX *mem_ctx)
901 {
902         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
903 }
904
905 static void notify_string(struct spoolss_notify_msg *msg,
906                           struct spoolss_Notify *data,
907                           TALLOC_CTX *mem_ctx)
908 {
909         /* The length of the message includes the trailing \0 */
910
911         data->data.string.size = msg->len * 2;
912         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
913         if (!data->data.string.string) {
914                 data->data.string.size = 0;
915                 return;
916         }
917 }
918
919 static void notify_system_time(struct spoolss_notify_msg *msg,
920                                struct spoolss_Notify *data,
921                                TALLOC_CTX *mem_ctx)
922 {
923         data->data.string.string = NULL;
924         data->data.string.size = 0;
925
926         if (msg->len != sizeof(time_t)) {
927                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
928                           msg->len));
929                 return;
930         }
931
932         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
933                                &data->data.string.string,
934                                &data->data.string.size);
935 }
936
937 struct notify2_message_table {
938         const char *name;
939         void (*fn)(struct spoolss_notify_msg *msg,
940                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
941 };
942
943 static struct notify2_message_table printer_notify_table[] = {
944         /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
945         /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
946         /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
947         /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
948         /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
949         /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
950         /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
951         /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
952         /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
953         /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
954         /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
955         /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
956         /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
957         /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
958         /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
959         /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
960         /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
961         /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
962         /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
963 };
964
965 static struct notify2_message_table job_notify_table[] = {
966         /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
967         /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
968         /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
969         /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
970         /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
971         /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
972         /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
973         /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
974         /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
975         /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
976         /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
977         /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
978         /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
979         /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
980         /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
981         /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
982         /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
983         /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
984         /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
985         /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
986         /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
987         /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
988         /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
989         /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
990 };
991
992
993 /***********************************************************************
994  Allocate talloc context for container object
995  **********************************************************************/
996
997 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
998 {
999         if ( !ctr )
1000                 return;
1001
1002         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
1003
1004         return;
1005 }
1006
1007 /***********************************************************************
1008  release all allocated memory and zero out structure
1009  **********************************************************************/
1010
1011 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1012 {
1013         if ( !ctr )
1014                 return;
1015
1016         if ( ctr->ctx )
1017                 talloc_destroy(ctr->ctx);
1018
1019         ZERO_STRUCTP(ctr);
1020
1021         return;
1022 }
1023
1024 /***********************************************************************
1025  **********************************************************************/
1026
1027 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1028 {
1029         if ( !ctr )
1030                 return NULL;
1031
1032         return ctr->ctx;
1033 }
1034
1035 /***********************************************************************
1036  **********************************************************************/
1037
1038 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1039 {
1040         if ( !ctr || !ctr->msg_groups )
1041                 return NULL;
1042
1043         if ( idx >= ctr->num_groups )
1044                 return NULL;
1045
1046         return &ctr->msg_groups[idx];
1047
1048 }
1049
1050 /***********************************************************************
1051  How many groups of change messages do we have ?
1052  **********************************************************************/
1053
1054 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1055 {
1056         if ( !ctr )
1057                 return 0;
1058
1059         return ctr->num_groups;
1060 }
1061
1062 /***********************************************************************
1063  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1064  **********************************************************************/
1065
1066 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1067 {
1068         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
1069         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
1070         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
1071         int                             i, new_slot;
1072
1073         if ( !ctr || !msg )
1074                 return 0;
1075
1076         /* loop over all groups looking for a matching printer name */
1077
1078         for ( i=0; i<ctr->num_groups; i++ ) {
1079                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1080                         break;
1081         }
1082
1083         /* add a new group? */
1084
1085         if ( i == ctr->num_groups ) {
1086                 ctr->num_groups++;
1087
1088                 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1089                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1090                         return 0;
1091                 }
1092                 ctr->msg_groups = groups;
1093
1094                 /* clear the new entry and set the printer name */
1095
1096                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1097                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1098         }
1099
1100         /* add the change messages; 'i' is the correct index now regardless */
1101
1102         msg_grp = &ctr->msg_groups[i];
1103
1104         msg_grp->num_msgs++;
1105
1106         if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1107                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1108                 return 0;
1109         }
1110         msg_grp->msgs = msg_list;
1111
1112         new_slot = msg_grp->num_msgs-1;
1113         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1114
1115         /* need to allocate own copy of data */
1116
1117         if ( msg->len != 0 )
1118                 msg_grp->msgs[new_slot].notify.data = (char *)
1119                         TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
1120
1121         return ctr->num_groups;
1122 }
1123
1124 static void construct_info_data(struct spoolss_Notify *info_data,
1125                                 enum spoolss_NotifyType type,
1126                                 uint16_t field, int id);
1127
1128 /***********************************************************************
1129  Send a change notication message on all handles which have a call
1130  back registered
1131  **********************************************************************/
1132
1133 static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1134                                   struct printer_handle *prn_hnd,
1135                                   SPOOLSS_NOTIFY_MSG *messages,
1136                                   uint32_t num_msgs,
1137                                   struct spoolss_Notify **_notifies,
1138                                   int *_count)
1139 {
1140         struct spoolss_Notify *notifies;
1141         SPOOLSS_NOTIFY_MSG *msg;
1142         int count = 0;
1143         uint32_t id;
1144         int i;
1145
1146         notifies = talloc_zero_array(mem_ctx,
1147                                      struct spoolss_Notify, num_msgs);
1148         if (!notifies) {
1149                 return ENOMEM;
1150         }
1151
1152         for (i = 0; i < num_msgs; i++) {
1153
1154                 msg = &messages[i];
1155
1156                 /* Are we monitoring this event? */
1157
1158                 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1159                         continue;
1160                 }
1161
1162                 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1163                            "for printer [%s]\n",
1164                            msg->type, msg->field, prn_hnd->sharename));
1165
1166                 /*
1167                  * if the is a printer notification handle and not a job
1168                  * notification type, then set the id to 0.
1169                  * Otherwise just use what was specified in the message.
1170                  *
1171                  * When registering change notification on a print server
1172                  * handle we always need to send back the id (snum) matching
1173                  * the printer for which the change took place.
1174                  * For change notify registered on a printer handle,
1175                  * this does not matter and the id should be 0.
1176                  *
1177                  * --jerry
1178                  */
1179
1180                 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1181                     (prn_hnd->printer_type == SPLHND_PRINTER)) {
1182                         id = 0;
1183                 } else {
1184                         id = msg->id;
1185                 }
1186
1187                 /* Convert unix jobid to smb jobid */
1188
1189                 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1190                         id = sysjob_to_jobid(msg->id);
1191
1192                         if (id == -1) {
1193                                 DEBUG(3, ("no such unix jobid %d\n",
1194                                           msg->id));
1195                                 continue;
1196                         }
1197                 }
1198
1199                 construct_info_data(&notifies[count],
1200                                     msg->type, msg->field, id);
1201
1202                 switch(msg->type) {
1203                 case PRINTER_NOTIFY_TYPE:
1204                         if (printer_notify_table[msg->field].fn) {
1205                                 printer_notify_table[msg->field].fn(msg,
1206                                                 &notifies[count], mem_ctx);
1207                         }
1208                         break;
1209
1210                 case JOB_NOTIFY_TYPE:
1211                         if (job_notify_table[msg->field].fn) {
1212                                 job_notify_table[msg->field].fn(msg,
1213                                                 &notifies[count], mem_ctx);
1214                         }
1215                         break;
1216
1217                 default:
1218                         DEBUG(5, ("Unknown notification type %d\n",
1219                                   msg->type));
1220                         continue;
1221                 }
1222
1223                 count++;
1224         }
1225
1226         *_notifies = notifies;
1227         *_count = count;
1228
1229         return 0;
1230 }
1231
1232 static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1233                                 struct printer_handle *prn_hnd,
1234                                 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1235 {
1236         struct spoolss_Notify *notifies;
1237         int count = 0;
1238         union spoolss_ReplyPrinterInfo info;
1239         struct spoolss_NotifyInfo info0;
1240         uint32_t reply_result;
1241         NTSTATUS status;
1242         WERROR werr;
1243         int ret;
1244
1245         /* Is there notification on this handle? */
1246         if (prn_hnd->notify.cli_chan == NULL ||
1247             prn_hnd->notify.cli_chan->active_connections == 0) {
1248                 return 0;
1249         }
1250
1251         DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1252                    prn_hnd->servername, prn_hnd->sharename));
1253
1254         /* For this printer? Print servers always receive notifications. */
1255         if ((prn_hnd->printer_type == SPLHND_PRINTER)  &&
1256             (!strequal(msg_group->printername, prn_hnd->sharename))) {
1257                 return 0;
1258         }
1259
1260         DEBUG(10,("Our printer\n"));
1261
1262         /* build the array of change notifications */
1263         ret = build_notify2_messages(mem_ctx, prn_hnd,
1264                                      msg_group->msgs,
1265                                      msg_group->num_msgs,
1266                                      &notifies, &count);
1267         if (ret) {
1268                 return ret;
1269         }
1270
1271         info0.version   = 0x2;
1272         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1273         info0.count     = count;
1274         info0.notifies  = notifies;
1275
1276         info.info0 = &info0;
1277
1278         status = dcerpc_spoolss_RouterReplyPrinterEx(
1279                                 prn_hnd->notify.cli_chan->binding_handle,
1280                                 mem_ctx,
1281                                 &prn_hnd->notify.cli_hnd,
1282                                 prn_hnd->notify.change, /* color */
1283                                 prn_hnd->notify.flags,
1284                                 &reply_result,
1285                                 0, /* reply_type, must be 0 */
1286                                 info, &werr);
1287         if (!NT_STATUS_IS_OK(status)) {
1288                 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1289                           "failed: %s\n",
1290                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1291                           nt_errstr(status)));
1292                 werr = ntstatus_to_werror(status);
1293         } else if (!W_ERROR_IS_OK(werr)) {
1294                 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1295                           "failed: %s\n",
1296                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1297                           win_errstr(werr)));
1298         }
1299         switch (reply_result) {
1300         case 0:
1301                 break;
1302         case PRINTER_NOTIFY_INFO_DISCARDED:
1303         case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1304         case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1305                 break;
1306         default:
1307                 break;
1308         }
1309
1310         return 0;
1311 }
1312
1313 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1314 {
1315         struct printer_handle    *p;
1316         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
1317         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1318         int ret;
1319
1320         if ( !msg_group ) {
1321                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1322                 return;
1323         }
1324
1325         if (!msg_group->msgs) {
1326                 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1327                 return;
1328         }
1329
1330         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1331
1332         /* loop over all printers */
1333
1334         for (p = printers_list; p; p = p->next) {
1335                 ret = send_notify2_printer(mem_ctx, p, msg_group);
1336                 if (ret) {
1337                         goto done;
1338                 }
1339         }
1340
1341 done:
1342         DEBUG(8,("send_notify2_changes: Exit...\n"));
1343         return;
1344 }
1345
1346 /***********************************************************************
1347  **********************************************************************/
1348
1349 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1350 {
1351
1352         uint32_t tv_sec, tv_usec;
1353         size_t offset = 0;
1354
1355         /* Unpack message */
1356
1357         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1358                              msg->printer);
1359
1360         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1361                                 &tv_sec, &tv_usec,
1362                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1363
1364         if (msg->len == 0)
1365                 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1366                            &msg->notify.value[0], &msg->notify.value[1]);
1367         else
1368                 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1369                            &msg->len, &msg->notify.data);
1370
1371         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1372                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1373
1374         tv->tv_sec = tv_sec;
1375         tv->tv_usec = tv_usec;
1376
1377         if (msg->len == 0)
1378                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1379                           msg->notify.value[1]));
1380         else
1381                 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1382
1383         return true;
1384 }
1385
1386 /********************************************************************
1387  Receive a notify2 message list
1388  ********************************************************************/
1389
1390 static void receive_notify2_message_list(struct messaging_context *msg,
1391                                          void *private_data,
1392                                          uint32_t msg_type,
1393                                          struct server_id server_id,
1394                                          DATA_BLOB *data)
1395 {
1396         size_t                  msg_count, i;
1397         char                    *buf = (char *)data->data;
1398         char                    *msg_ptr;
1399         size_t                  msg_len;
1400         SPOOLSS_NOTIFY_MSG      notify;
1401         SPOOLSS_NOTIFY_MSG_CTR  messages;
1402         int                     num_groups;
1403
1404         if (data->length < 4) {
1405                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1406                 return;
1407         }
1408
1409         msg_count = IVAL(buf, 0);
1410         msg_ptr = buf + 4;
1411
1412         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1413
1414         if (msg_count == 0) {
1415                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1416                 return;
1417         }
1418
1419         /* initialize the container */
1420
1421         ZERO_STRUCT( messages );
1422         notify_msg_ctr_init( &messages );
1423
1424         /*
1425          * build message groups for each printer identified
1426          * in a change_notify msg.  Remember that a PCN message
1427          * includes the handle returned for the srv_spoolss_replyopenprinter()
1428          * call.  Therefore messages are grouped according to printer handle.
1429          */
1430
1431         for ( i=0; i<msg_count; i++ ) {
1432                 struct timeval msg_tv;
1433
1434                 if (msg_ptr + 4 - buf > data->length) {
1435                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1436                         return;
1437                 }
1438
1439                 msg_len = IVAL(msg_ptr,0);
1440                 msg_ptr += 4;
1441
1442                 if (msg_ptr + msg_len - buf > data->length) {
1443                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1444                         return;
1445                 }
1446
1447                 /* unpack messages */
1448
1449                 ZERO_STRUCT( notify );
1450                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1451                 msg_ptr += msg_len;
1452
1453                 /* add to correct list in container */
1454
1455                 notify_msg_ctr_addmsg( &messages, &notify );
1456
1457                 /* free memory that might have been allocated by notify2_unpack_msg() */
1458
1459                 if ( notify.len != 0 )
1460                         SAFE_FREE( notify.notify.data );
1461         }
1462
1463         /* process each group of messages */
1464
1465         num_groups = notify_msg_ctr_numgroups( &messages );
1466         for ( i=0; i<num_groups; i++ )
1467                 send_notify2_changes( &messages, i );
1468
1469
1470         /* cleanup */
1471
1472         DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1473                 (uint32_t)msg_count ));
1474
1475         notify_msg_ctr_destroy( &messages );
1476
1477         return;
1478 }
1479
1480 /********************************************************************
1481  Send a message to ourself about new driver being installed
1482  so we can upgrade the information for each printer bound to this
1483  driver
1484  ********************************************************************/
1485
1486 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1487                                             struct messaging_context *msg_ctx)
1488 {
1489         int len = strlen(drivername);
1490
1491         if (!len)
1492                 return false;
1493
1494         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1495                 drivername));
1496
1497         messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1498                            MSG_PRINTER_DRVUPGRADE,
1499                            (uint8_t *)drivername, len+1);
1500
1501         return true;
1502 }
1503
1504 void srv_spoolss_cleanup(void)
1505 {
1506         struct printer_session_counter *session_counter;
1507
1508         for (session_counter = counter_list;
1509              session_counter != NULL;
1510              session_counter = counter_list) {
1511                 DLIST_REMOVE(counter_list, session_counter);
1512                 TALLOC_FREE(session_counter);
1513         }
1514 }
1515
1516 /**********************************************************************
1517  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1518  over all printers, upgrading ones as necessary
1519  **********************************************************************/
1520
1521 void do_drv_upgrade_printer(struct messaging_context *msg,
1522                             void *private_data,
1523                             uint32_t msg_type,
1524                             struct server_id server_id,
1525                             DATA_BLOB *data)
1526 {
1527         TALLOC_CTX *tmp_ctx;
1528         struct auth_serversupplied_info *session_info = NULL;
1529         struct spoolss_PrinterInfo2 *pinfo2;
1530         NTSTATUS status;
1531         WERROR result;
1532         const char *drivername;
1533         int snum;
1534         int n_services = lp_numservices();
1535
1536         tmp_ctx = talloc_new(NULL);
1537         if (!tmp_ctx) return;
1538
1539         status = make_session_info_system(tmp_ctx, &session_info);
1540         if (!NT_STATUS_IS_OK(status)) {
1541                 DEBUG(0, ("do_drv_upgrade_printer: "
1542                           "Could not create system session_info\n"));
1543                 goto done;
1544         }
1545
1546         drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1547         if (!drivername) {
1548                 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1549                 goto done;
1550         }
1551
1552         DEBUG(10, ("do_drv_upgrade_printer: "
1553                    "Got message for new driver [%s]\n", drivername));
1554
1555         /* Iterate the printer list */
1556
1557         for (snum = 0; snum < n_services; snum++) {
1558                 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1559                         continue;
1560                 }
1561
1562                 /* ignore [printers] share */
1563                 if (strequal(lp_const_servicename(snum), "printers")) {
1564                         continue;
1565                 }
1566
1567                 result = winreg_get_printer(tmp_ctx, session_info, msg,
1568                                             lp_const_servicename(snum),
1569                                             &pinfo2);
1570
1571                 if (!W_ERROR_IS_OK(result)) {
1572                         continue;
1573                 }
1574
1575                 if (!pinfo2->drivername) {
1576                         continue;
1577                 }
1578
1579                 if (strcmp(drivername, pinfo2->drivername) != 0) {
1580                         continue;
1581                 }
1582
1583                 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1584
1585                 /* all we care about currently is the change_id */
1586                 result = winreg_printer_update_changeid(tmp_ctx,
1587                                                         session_info,
1588                                                         msg,
1589                                                         pinfo2->printername);
1590
1591                 if (!W_ERROR_IS_OK(result)) {
1592                         DEBUG(3, ("do_drv_upgrade_printer: "
1593                                   "Failed to update changeid [%s]\n",
1594                                   win_errstr(result)));
1595                 }
1596         }
1597
1598         /* all done */
1599 done:
1600         talloc_free(tmp_ctx);
1601 }
1602
1603 /********************************************************************
1604  Update the cache for all printq's with a registered client
1605  connection
1606  ********************************************************************/
1607
1608 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1609 {
1610         struct printer_handle *printer = printers_list;
1611         int snum;
1612
1613         /* loop through all printers and update the cache where
1614            a client is connected */
1615         while (printer) {
1616                 if ((printer->printer_type == SPLHND_PRINTER) &&
1617                     ((printer->notify.cli_chan != NULL) &&
1618                      (printer->notify.cli_chan->active_connections > 0))) {
1619                         snum = print_queue_snum(printer->sharename);
1620                         print_queue_status(msg_ctx, snum, NULL, NULL);
1621                 }
1622
1623                 printer = printer->next;
1624         }
1625
1626         return;
1627 }
1628
1629 /****************************************************************
1630  _spoolss_OpenPrinter
1631 ****************************************************************/
1632
1633 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1634                             struct spoolss_OpenPrinter *r)
1635 {
1636         struct spoolss_OpenPrinterEx e;
1637         WERROR werr;
1638
1639         ZERO_STRUCT(e.in.userlevel);
1640
1641         e.in.printername        = r->in.printername;
1642         e.in.datatype           = r->in.datatype;
1643         e.in.devmode_ctr        = r->in.devmode_ctr;
1644         e.in.access_mask        = r->in.access_mask;
1645         e.in.level              = 0;
1646
1647         e.out.handle            = r->out.handle;
1648
1649         werr = _spoolss_OpenPrinterEx(p, &e);
1650
1651         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1652                 /* OpenPrinterEx returns this for a bad
1653                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1654                  * instead.
1655                  */
1656                 werr = WERR_INVALID_PRINTER_NAME;
1657         }
1658
1659         return werr;
1660 }
1661
1662 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1663                               struct spoolss_DeviceMode *orig,
1664                               struct spoolss_DeviceMode **dest)
1665 {
1666         struct spoolss_DeviceMode *dm;
1667
1668         dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1669         if (!dm) {
1670                 return WERR_NOMEM;
1671         }
1672
1673         /* copy all values, then duplicate strings and structs */
1674         *dm = *orig;
1675
1676         dm->devicename = talloc_strdup(dm, orig->devicename);
1677         if (!dm->devicename) {
1678                 return WERR_NOMEM;
1679         }
1680         dm->formname = talloc_strdup(dm, orig->formname);
1681         if (!dm->formname) {
1682                 return WERR_NOMEM;
1683         }
1684         if (orig->driverextra_data.data) {
1685                 dm->driverextra_data.data =
1686                         (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1687                                         orig->driverextra_data.length);
1688                 if (!dm->driverextra_data.data) {
1689                         return WERR_NOMEM;
1690                 }
1691         }
1692
1693         *dest = dm;
1694         return WERR_OK;
1695 }
1696
1697 /****************************************************************
1698  _spoolss_OpenPrinterEx
1699 ****************************************************************/
1700
1701 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1702                               struct spoolss_OpenPrinterEx *r)
1703 {
1704         int snum;
1705         struct printer_handle *Printer=NULL;
1706         WERROR result;
1707
1708         if (!r->in.printername) {
1709                 return WERR_INVALID_PARAM;
1710         }
1711
1712         if (r->in.level < 0 || r->in.level > 3) {
1713                 return WERR_INVALID_PARAM;
1714         }
1715         if ((r->in.level == 1 && !r->in.userlevel.level1) ||
1716             (r->in.level == 2 && !r->in.userlevel.level2) ||
1717             (r->in.level == 3 && !r->in.userlevel.level3)) {
1718                 return WERR_INVALID_PARAM;
1719         }
1720
1721         /* some sanity check because you can open a printer or a print server */
1722         /* aka: \\server\printer or \\server */
1723
1724         DEBUGADD(3,("checking name: %s\n", r->in.printername));
1725
1726         result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1727         if (!W_ERROR_IS_OK(result)) {
1728                 DEBUG(0,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1729                         "for printer %s\n", r->in.printername));
1730                 ZERO_STRUCTP(r->out.handle);
1731                 return result;
1732         }
1733
1734         Printer = find_printer_index_by_hnd(p, r->out.handle);
1735         if ( !Printer ) {
1736                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1737                         "handle we created for printer %s\n", r->in.printername));
1738                 close_printer_handle(p, r->out.handle);
1739                 ZERO_STRUCTP(r->out.handle);
1740                 return WERR_INVALID_PARAM;
1741         }
1742
1743         /*
1744          * First case: the user is opening the print server:
1745          *
1746          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1747          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1748          *
1749          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1750          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1751          * or if the user is listed in the smb.conf printer admin parameter.
1752          *
1753          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1754          * client view printer folder, but does not show the MSAPW.
1755          *
1756          * Note: this test needs code to check access rights here too. Jeremy
1757          * could you look at this?
1758          *
1759          * Second case: the user is opening a printer:
1760          * NT doesn't let us connect to a printer if the connecting user
1761          * doesn't have print permission.
1762          *
1763          * Third case: user is opening a Port Monitor
1764          * access checks same as opening a handle to the print server.
1765          */
1766
1767         switch (Printer->printer_type )
1768         {
1769         case SPLHND_SERVER:
1770         case SPLHND_PORTMON_TCP:
1771         case SPLHND_PORTMON_LOCAL:
1772                 /* Printserver handles use global struct... */
1773
1774                 snum = -1;
1775
1776                 /* Map standard access rights to object specific access rights */
1777
1778                 se_map_standard(&r->in.access_mask,
1779                                 &printserver_std_mapping);
1780
1781                 /* Deny any object specific bits that don't apply to print
1782                    servers (i.e printer and job specific bits) */
1783
1784                 r->in.access_mask &= SEC_MASK_SPECIFIC;
1785
1786                 if (r->in.access_mask &
1787                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1788                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1789                         close_printer_handle(p, r->out.handle);
1790                         ZERO_STRUCTP(r->out.handle);
1791                         return WERR_ACCESS_DENIED;
1792                 }
1793
1794                 /* Allow admin access */
1795
1796                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1797                 {
1798                         if (!lp_ms_add_printer_wizard()) {
1799                                 close_printer_handle(p, r->out.handle);
1800                                 ZERO_STRUCTP(r->out.handle);
1801                                 return WERR_ACCESS_DENIED;
1802                         }
1803
1804                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1805                            and not a printer admin, then fail */
1806
1807                         if ((p->session_info->utok.uid != sec_initial_uid()) &&
1808                             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
1809                             !nt_token_check_sid(&global_sid_Builtin_Print_Operators, p->session_info->security_token) &&
1810                             !token_contains_name_in_list(
1811                                     uidtoname(p->session_info->utok.uid),
1812                                     p->session_info->info3->base.domain.string,
1813                                     NULL,
1814                                     p->session_info->security_token,
1815                                     lp_printer_admin(snum))) {
1816                                 close_printer_handle(p, r->out.handle);
1817                                 ZERO_STRUCTP(r->out.handle);
1818                                 DEBUG(3,("access DENIED as user is not root, "
1819                                         "has no printoperator privilege, "
1820                                         "not a member of the printoperator builtin group and "
1821                                         "is not in printer admin list"));
1822                                 return WERR_ACCESS_DENIED;
1823                         }
1824
1825                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1826                 }
1827                 else
1828                 {
1829                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1830                 }
1831
1832                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1833                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1834
1835                 /* We fall through to return WERR_OK */
1836                 break;
1837
1838         case SPLHND_PRINTER:
1839                 /* NT doesn't let us connect to a printer if the connecting user
1840                    doesn't have print permission.  */
1841
1842                 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1843                         close_printer_handle(p, r->out.handle);
1844                         ZERO_STRUCTP(r->out.handle);
1845                         return WERR_BADFID;
1846                 }
1847
1848                 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1849                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1850                 }
1851
1852                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1853
1854                 /* map an empty access mask to the minimum access mask */
1855                 if (r->in.access_mask == 0x0)
1856                         r->in.access_mask = PRINTER_ACCESS_USE;
1857
1858                 /*
1859                  * If we are not serving the printer driver for this printer,
1860                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1861                  * will keep NT clients happy  --jerry
1862                  */
1863
1864                 if (lp_use_client_driver(snum)
1865                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1866                 {
1867                         r->in.access_mask = PRINTER_ACCESS_USE;
1868                 }
1869
1870                 /* check smb.conf parameters and the the sec_desc */
1871
1872                 if (!allow_access(lp_hostsdeny(snum), lp_hostsallow(snum),
1873                                   p->client_id->name, p->client_id->addr)) {
1874                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1875                         ZERO_STRUCTP(r->out.handle);
1876                         return WERR_ACCESS_DENIED;
1877                 }
1878
1879                 if (!user_ok_token(uidtoname(p->session_info->utok.uid), NULL,
1880                                    p->session_info->security_token, snum) ||
1881                     !print_access_check(p->session_info,
1882                                         p->msg_ctx,
1883                                         snum,
1884                                         r->in.access_mask)) {
1885                         DEBUG(3, ("access DENIED for printer open\n"));
1886                         close_printer_handle(p, r->out.handle);
1887                         ZERO_STRUCTP(r->out.handle);
1888                         return WERR_ACCESS_DENIED;
1889                 }
1890
1891                 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1892                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1893                         close_printer_handle(p, r->out.handle);
1894                         ZERO_STRUCTP(r->out.handle);
1895                         return WERR_ACCESS_DENIED;
1896                 }
1897
1898                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1899                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1900                 else
1901                         r->in.access_mask = PRINTER_ACCESS_USE;
1902
1903                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1904                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1905
1906                 winreg_create_printer(p->mem_ctx,
1907                                       get_session_info_system(),
1908                                       p->msg_ctx,
1909                                       lp_const_servicename(snum));
1910
1911                 break;
1912
1913         default:
1914                 /* sanity check to prevent programmer error */
1915                 ZERO_STRUCTP(r->out.handle);
1916                 return WERR_BADFID;
1917         }
1918
1919         Printer->access_granted = r->in.access_mask;
1920
1921         /*
1922          * If the client sent a devmode in the OpenPrinter() call, then
1923          * save it here in case we get a job submission on this handle
1924          */
1925
1926          if ((Printer->printer_type != SPLHND_SERVER) &&
1927              r->in.devmode_ctr.devmode) {
1928                 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1929                                 &Printer->devmode);
1930          }
1931
1932 #if 0   /* JERRY -- I'm doubtful this is really effective */
1933         /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1934            optimization in Windows 2000 clients  --jerry */
1935
1936         if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1937                 && (RA_WIN2K == get_remote_arch()) )
1938         {
1939                 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1940                 sys_usleep( 500000 );
1941         }
1942 #endif
1943
1944         return WERR_OK;
1945 }
1946
1947 /****************************************************************
1948  _spoolss_ClosePrinter
1949 ****************************************************************/
1950
1951 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1952                              struct spoolss_ClosePrinter *r)
1953 {
1954         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1955
1956         if (Printer && Printer->document_started) {
1957                 struct spoolss_EndDocPrinter e;
1958
1959                 e.in.handle = r->in.handle;
1960
1961                 _spoolss_EndDocPrinter(p, &e);
1962         }
1963
1964         if (!close_printer_handle(p, r->in.handle))
1965                 return WERR_BADFID;
1966
1967         /* clear the returned printer handle.  Observed behavior
1968            from Win2k server.  Don't think this really matters.
1969            Previous code just copied the value of the closed
1970            handle.    --jerry */
1971
1972         ZERO_STRUCTP(r->out.handle);
1973
1974         return WERR_OK;
1975 }
1976
1977 /****************************************************************
1978  _spoolss_DeletePrinter
1979 ****************************************************************/
1980
1981 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
1982                               struct spoolss_DeletePrinter *r)
1983 {
1984         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1985         WERROR result;
1986         int snum;
1987
1988         if (Printer && Printer->document_started) {
1989                 struct spoolss_EndDocPrinter e;
1990
1991                 e.in.handle = r->in.handle;
1992
1993                 _spoolss_EndDocPrinter(p, &e);
1994         }
1995
1996         if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
1997                 winreg_delete_printer_key(p->mem_ctx,
1998                                           get_session_info_system(),
1999                                           p->msg_ctx,
2000                                           lp_const_servicename(snum),
2001                                           "");
2002         }
2003
2004         result = delete_printer_handle(p, r->in.handle);
2005
2006         return result;
2007 }
2008
2009 /*******************************************************************
2010  * static function to lookup the version id corresponding to an
2011  * long architecture string
2012  ******************************************************************/
2013
2014 static const struct print_architecture_table_node archi_table[]= {
2015
2016         {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
2017         {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
2018         {"Windows NT R4000",     SPL_ARCH_W32MIPS,      2 },
2019         {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,     2 },
2020         {"Windows NT PowerPC",   SPL_ARCH_W32PPC,       2 },
2021         {"Windows IA64",         SPL_ARCH_IA64,         3 },
2022         {"Windows x64",          SPL_ARCH_X64,          3 },
2023         {NULL,                   "",            -1 }
2024 };
2025
2026 static int get_version_id(const char *arch)
2027 {
2028         int i;
2029
2030         for (i=0; archi_table[i].long_archi != NULL; i++)
2031         {
2032                 if (strcmp(arch, archi_table[i].long_archi) == 0)
2033                         return (archi_table[i].version);
2034         }
2035
2036         return -1;
2037 }
2038
2039 /****************************************************************
2040  _spoolss_DeletePrinterDriver
2041 ****************************************************************/
2042
2043 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2044                                     struct spoolss_DeletePrinterDriver *r)
2045 {
2046
2047         struct spoolss_DriverInfo8 *info = NULL;
2048         struct spoolss_DriverInfo8 *info_win2k = NULL;
2049         int                             version;
2050         WERROR                          status;
2051
2052         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2053            and not a printer admin, then fail */
2054
2055         if ( (p->session_info->utok.uid != sec_initial_uid())
2056              && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2057                 && !token_contains_name_in_list(
2058                         uidtoname(p->session_info->utok.uid),
2059                         p->session_info->info3->base.domain.string,
2060                         NULL,
2061                         p->session_info->security_token,
2062                         lp_printer_admin(-1)) )
2063         {
2064                 return WERR_ACCESS_DENIED;
2065         }
2066
2067         /* check that we have a valid driver name first */
2068
2069         if ((version = get_version_id(r->in.architecture)) == -1)
2070                 return WERR_INVALID_ENVIRONMENT;
2071
2072         status = winreg_get_driver(p->mem_ctx,
2073                                    get_session_info_system(),
2074                                    p->msg_ctx,
2075                                    r->in.architecture, r->in.driver,
2076                                    version, &info);
2077         if (!W_ERROR_IS_OK(status)) {
2078                 /* try for Win2k driver if "Windows NT x86" */
2079
2080                 if ( version == 2 ) {
2081                         version = 3;
2082
2083                         status = winreg_get_driver(p->mem_ctx,
2084                                                    get_session_info_system(),
2085                                                    p->msg_ctx,
2086                                                    r->in.architecture,
2087                                                    r->in.driver,
2088                                                    version, &info);
2089                         if (!W_ERROR_IS_OK(status)) {
2090                                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2091                                 goto done;
2092                         }
2093                 }
2094                 /* otherwise it was a failure */
2095                 else {
2096                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2097                         goto done;
2098                 }
2099
2100         }
2101
2102         if (printer_driver_in_use(p->mem_ctx,
2103                                   get_session_info_system(),
2104                                   p->msg_ctx,
2105                                   info)) {
2106                 status = WERR_PRINTER_DRIVER_IN_USE;
2107                 goto done;
2108         }
2109
2110         if (version == 2) {
2111                 status = winreg_get_driver(p->mem_ctx,
2112                                            get_session_info_system(),
2113                                            p->msg_ctx,
2114                                            r->in.architecture,
2115                                            r->in.driver, 3, &info_win2k);
2116                 if (W_ERROR_IS_OK(status)) {
2117                         /* if we get to here, we now have 2 driver info structures to remove */
2118                         /* remove the Win2k driver first*/
2119
2120                         status = winreg_del_driver(p->mem_ctx,
2121                                                    get_session_info_system(),
2122                                                    p->msg_ctx,
2123                                                    info_win2k, 3);
2124                         talloc_free(info_win2k);
2125
2126                         /* this should not have failed---if it did, report to client */
2127                         if (!W_ERROR_IS_OK(status)) {
2128                                 goto done;
2129                         }
2130                 }
2131         }
2132
2133         status = winreg_del_driver(p->mem_ctx,
2134                                    get_session_info_system(),
2135                                    p->msg_ctx,
2136                                    info, version);
2137
2138 done:
2139         talloc_free(info);
2140
2141         return status;
2142 }
2143
2144 /****************************************************************
2145  _spoolss_DeletePrinterDriverEx
2146 ****************************************************************/
2147
2148 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2149                                       struct spoolss_DeletePrinterDriverEx *r)
2150 {
2151         struct spoolss_DriverInfo8      *info = NULL;
2152         struct spoolss_DriverInfo8      *info_win2k = NULL;
2153         int                             version;
2154         bool                            delete_files;
2155         WERROR                          status;
2156
2157         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2158            and not a printer admin, then fail */
2159
2160         if ( (p->session_info->utok.uid != sec_initial_uid())
2161                 && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2162                 && !token_contains_name_in_list(
2163                         uidtoname(p->session_info->utok.uid),
2164                         p->session_info->info3->base.domain.string,
2165                         NULL,
2166                         p->session_info->security_token, lp_printer_admin(-1)) )
2167         {
2168                 return WERR_ACCESS_DENIED;
2169         }
2170
2171         /* check that we have a valid driver name first */
2172         if ((version = get_version_id(r->in.architecture)) == -1) {
2173                 /* this is what NT returns */
2174                 return WERR_INVALID_ENVIRONMENT;
2175         }
2176
2177         if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2178                 version = r->in.version;
2179
2180         status = winreg_get_driver(p->mem_ctx,
2181                                    get_session_info_system(),
2182                                    p->msg_ctx,
2183                                    r->in.architecture,
2184                                    r->in.driver,
2185                                    version,
2186                                    &info);
2187         if (!W_ERROR_IS_OK(status)) {
2188                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2189
2190                 /*
2191                  * if the client asked for a specific version,
2192                  * or this is something other than Windows NT x86,
2193                  * then we've failed
2194                  */
2195
2196                 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2197                         goto done;
2198
2199                 /* try for Win2k driver if "Windows NT x86" */
2200
2201                 version = 3;
2202                 status = winreg_get_driver(info,
2203                                            get_session_info_system(),
2204                                            p->msg_ctx,
2205                                            r->in.architecture,
2206                                            r->in.driver,
2207                                            version, &info);
2208                 if (!W_ERROR_IS_OK(status)) {
2209                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2210                         goto done;
2211                 }
2212         }
2213
2214         if (printer_driver_in_use(info,
2215                                   get_session_info_system(),
2216                                   p->msg_ctx,
2217                                   info)) {
2218                 status = WERR_PRINTER_DRIVER_IN_USE;
2219                 goto done;
2220         }
2221
2222         /*
2223          * we have a couple of cases to consider.
2224          * (1) Are any files in use?  If so and DPD_DELTE_ALL_FILE is set,
2225          *     then the delete should fail if **any** files overlap with
2226          *     other drivers
2227          * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2228          *     non-overlapping files
2229          * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2230          *     is set, the do not delete any files
2231          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2232          */
2233
2234         delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2235
2236         /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2237
2238         if (delete_files &&
2239             (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2240             printer_driver_files_in_use(info,
2241                                         get_session_info_system(),
2242                                         p->msg_ctx,
2243                                         info)) {
2244                 /* no idea of the correct error here */
2245                 status = WERR_ACCESS_DENIED;
2246                 goto done;
2247         }
2248
2249
2250         /* also check for W32X86/3 if necessary; maybe we already have? */
2251
2252         if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION)  ) {
2253                 status = winreg_get_driver(info,
2254                                            get_session_info_system(),
2255                                            p->msg_ctx,
2256                                            r->in.architecture,
2257                                            r->in.driver, 3, &info_win2k);
2258                 if (W_ERROR_IS_OK(status)) {
2259
2260                         if (delete_files &&
2261                             (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2262                             printer_driver_files_in_use(info,
2263                                                         get_session_info_system(),
2264                                                         p->msg_ctx,
2265                                                         info_win2k)) {
2266                                 /* no idea of the correct error here */
2267                                 talloc_free(info_win2k);
2268                                 status = WERR_ACCESS_DENIED;
2269                                 goto done;
2270                         }
2271
2272                         /* if we get to here, we now have 2 driver info structures to remove */
2273                         /* remove the Win2k driver first*/
2274
2275                         status = winreg_del_driver(info,
2276                                                    get_session_info_system(),
2277                                                    p->msg_ctx,
2278                                                    info_win2k,
2279                                                    3);
2280
2281                         /* this should not have failed---if it did, report to client */
2282
2283                         if (!W_ERROR_IS_OK(status)) {
2284                                 goto done;
2285                         }
2286
2287                         /*
2288                          * now delete any associated files if delete_files is
2289                          * true. Even if this part failes, we return succes
2290                          * because the driver doesn not exist any more
2291                          */
2292                         if (delete_files) {
2293                                 delete_driver_files(get_session_info_system(),
2294                                                     info_win2k);
2295                         }
2296                 }
2297         }
2298
2299         status = winreg_del_driver(info,
2300                                    get_session_info_system(),
2301                                    p->msg_ctx,
2302                                    info,
2303                                    version);
2304         if (!W_ERROR_IS_OK(status)) {
2305                 goto done;
2306         }
2307
2308         /*
2309          * now delete any associated files if delete_files is
2310          * true. Even if this part failes, we return succes
2311          * because the driver doesn not exist any more
2312          */
2313         if (delete_files) {
2314                 delete_driver_files(get_session_info_system(), info);
2315         }
2316
2317 done:
2318         talloc_free(info);
2319         return status;
2320 }
2321
2322
2323 /********************************************************************
2324  GetPrinterData on a printer server Handle.
2325 ********************************************************************/
2326
2327 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2328                                             const char *value,
2329                                             enum winreg_Type *type,
2330                                             union spoolss_PrinterData *data)
2331 {
2332         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2333
2334         if (!StrCaseCmp(value, "W3SvcInstalled")) {
2335                 *type = REG_DWORD;
2336                 data->value = 0x00;
2337                 return WERR_OK;
2338         }
2339
2340         if (!StrCaseCmp(value, "BeepEnabled")) {
2341                 *type = REG_DWORD;
2342                 data->value = 0x00;
2343                 return WERR_OK;
2344         }
2345
2346         if (!StrCaseCmp(value, "EventLog")) {
2347                 *type = REG_DWORD;
2348                 /* formally was 0x1b */
2349                 data->value = 0x00;
2350                 return WERR_OK;
2351         }
2352
2353         if (!StrCaseCmp(value, "NetPopup")) {
2354                 *type = REG_DWORD;
2355                 data->value = 0x00;
2356                 return WERR_OK;
2357         }
2358
2359         if (!StrCaseCmp(value, "MajorVersion")) {
2360                 *type = REG_DWORD;
2361
2362                 /* Windows NT 4.0 seems to not allow uploading of drivers
2363                    to a server that reports 0x3 as the MajorVersion.
2364                    need to investigate more how Win2k gets around this .
2365                    -- jerry */
2366
2367                 if (RA_WINNT == get_remote_arch()) {
2368                         data->value = 0x02;
2369                 } else {
2370                         data->value = 0x03;
2371                 }
2372
2373                 return WERR_OK;
2374         }
2375
2376         if (!StrCaseCmp(value, "MinorVersion")) {
2377                 *type = REG_DWORD;
2378                 data->value = 0x00;
2379                 return WERR_OK;
2380         }
2381
2382         /* REG_BINARY
2383          *  uint32_t size        = 0x114
2384          *  uint32_t major       = 5
2385          *  uint32_t minor       = [0|1]
2386          *  uint32_t build       = [2195|2600]
2387          *  extra unicode string = e.g. "Service Pack 3"
2388          */
2389         if (!StrCaseCmp(value, "OSVersion")) {
2390                 DATA_BLOB blob;
2391                 enum ndr_err_code ndr_err;
2392                 struct spoolss_OSVersion os;
2393
2394                 os.major                = 5;    /* Windows 2000 == 5.0 */
2395                 os.minor                = 0;
2396                 os.build                = 2195; /* build */
2397                 os.extra_string         = "";   /* leave extra string empty */
2398
2399                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2400                         (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2401                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2402                         return WERR_GENERAL_FAILURE;
2403                 }
2404
2405                 *type = REG_BINARY;
2406                 data->binary = blob;
2407
2408                 return WERR_OK;
2409         }
2410
2411
2412         if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2413                 *type = REG_SZ;
2414
2415                 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2416                 W_ERROR_HAVE_NO_MEMORY(data->string);
2417
2418                 return WERR_OK;
2419         }
2420
2421         if (!StrCaseCmp(value, "Architecture")) {
2422                 *type = REG_SZ;
2423                 data->string = talloc_strdup(mem_ctx,
2424                         lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2425                 W_ERROR_HAVE_NO_MEMORY(data->string);
2426
2427                 return WERR_OK;
2428         }
2429
2430         if (!StrCaseCmp(value, "DsPresent")) {
2431                 *type = REG_DWORD;
2432
2433                 /* only show the publish check box if we are a
2434                    member of a AD domain */
2435
2436                 if (lp_security() == SEC_ADS) {
2437                         data->value = 0x01;
2438                 } else {
2439                         data->value = 0x00;
2440                 }
2441                 return WERR_OK;
2442         }
2443
2444         if (!StrCaseCmp(value, "DNSMachineName")) {
2445                 const char *hostname = get_mydnsfullname();
2446
2447                 if (!hostname) {
2448                         return WERR_BADFILE;
2449                 }
2450
2451                 *type = REG_SZ;
2452                 data->string = talloc_strdup(mem_ctx, hostname);
2453                 W_ERROR_HAVE_NO_MEMORY(data->string);
2454
2455                 return WERR_OK;
2456         }
2457
2458         *type = REG_NONE;
2459
2460         return WERR_INVALID_PARAM;
2461 }
2462
2463 /****************************************************************
2464  _spoolss_GetPrinterData
2465 ****************************************************************/
2466
2467 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2468                                struct spoolss_GetPrinterData *r)
2469 {
2470         struct spoolss_GetPrinterDataEx r2;
2471
2472         r2.in.handle            = r->in.handle;
2473         r2.in.key_name          = "PrinterDriverData";
2474         r2.in.value_name        = r->in.value_name;
2475         r2.in.offered           = r->in.offered;
2476         r2.out.type             = r->out.type;
2477         r2.out.data             = r->out.data;
2478         r2.out.needed           = r->out.needed;
2479
2480         return _spoolss_GetPrinterDataEx(p, &r2);
2481 }
2482
2483 /*********************************************************
2484  Connect to the client machine.
2485 **********************************************************/
2486
2487 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2488                         struct sockaddr_storage *client_ss, const char *remote_machine)
2489 {
2490         NTSTATUS ret;
2491         struct cli_state *the_cli;
2492         struct sockaddr_storage rm_addr;
2493         char addr[INET6_ADDRSTRLEN];
2494
2495         if ( is_zero_addr(client_ss) ) {
2496                 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2497                         remote_machine));
2498                 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2499                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2500                         return false;
2501                 }
2502                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2503         } else {
2504                 rm_addr = *client_ss;
2505                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2506                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2507                         addr));
2508         }
2509
2510         if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2511                 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2512                         addr));
2513                 return false;
2514         }
2515
2516         /* setup the connection */
2517         ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2518                 &rm_addr, 0, "IPC$", "IPC",
2519                 "", /* username */
2520                 "", /* domain */
2521                 "", /* password */
2522                 0, lp_client_signing());
2523
2524         if ( !NT_STATUS_IS_OK( ret ) ) {
2525                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2526                         remote_machine ));
2527                 return false;
2528         }
2529
2530         if ( the_cli->protocol != PROTOCOL_NT1 ) {
2531                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2532                 cli_shutdown(the_cli);
2533                 return false;
2534         }
2535
2536         /*
2537          * Ok - we have an anonymous connection to the IPC$ share.
2538          * Now start the NT Domain stuff :-).
2539          */
2540
2541         ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2542         if (!NT_STATUS_IS_OK(ret)) {
2543                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2544                         remote_machine, nt_errstr(ret)));
2545                 cli_shutdown(the_cli);
2546                 return false;
2547         }
2548
2549         return true;
2550 }
2551
2552 /***************************************************************************
2553  Connect to the client.
2554 ****************************************************************************/
2555
2556 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2557                                         uint32_t localprinter,
2558                                         enum winreg_Type type,
2559                                         struct policy_handle *handle,
2560                                         struct notify_back_channel **_chan,
2561                                         struct sockaddr_storage *client_ss,
2562                                         struct messaging_context *msg_ctx)
2563 {
2564         WERROR result;
2565         NTSTATUS status;
2566         struct notify_back_channel *chan;
2567
2568         for (chan = back_channels; chan; chan = chan->next) {
2569                 if (memcmp(&chan->client_address, client_ss,
2570                            sizeof(struct sockaddr_storage)) == 0) {
2571                         break;
2572                 }
2573         }
2574
2575         /*
2576          * If it's the first connection, contact the client
2577          * and connect to the IPC$ share anonymously
2578          */
2579         if (!chan) {
2580                 fstring unix_printer;
2581
2582                 /* the +2 is to strip the leading 2 backslashs */
2583                 fstrcpy(unix_printer, printer + 2);
2584
2585                 chan = talloc_zero(back_channels, struct notify_back_channel);
2586                 if (!chan) {
2587                         return false;
2588                 }
2589                 chan->client_address = *client_ss;
2590
2591                 if (!spoolss_connect_to_client(&chan->cli_pipe, client_ss, unix_printer)) {
2592                         TALLOC_FREE(chan);
2593                         return false;
2594                 }
2595                 chan->binding_handle = chan->cli_pipe->binding_handle;
2596
2597                 DLIST_ADD(back_channels, chan);
2598
2599                 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2600                                    receive_notify2_message_list);
2601                 /* Tell the connections db we're now interested in printer
2602                  * notify messages. */
2603                 serverid_register_msg_flags(messaging_server_id(msg_ctx),
2604                                             true, FLAG_MSG_PRINT_NOTIFY);
2605         }
2606
2607         /*
2608          * Tell the specific printing tdb we want messages for this printer
2609          * by registering our PID.
2610          */
2611
2612         if (!print_notify_register_pid(snum)) {
2613                 DEBUG(0, ("Failed to register our pid for printer %s\n",
2614                           printer));
2615         }
2616
2617         status = dcerpc_spoolss_ReplyOpenPrinter(chan->binding_handle,
2618                                                  talloc_tos(),
2619                                                  printer,
2620                                                  localprinter,
2621                                                  type,
2622                                                  0,
2623                                                  NULL,
2624                                                  handle,
2625                                                  &result);
2626         if (!NT_STATUS_IS_OK(status)) {
2627                 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2628                 result = ntstatus_to_werror(status);
2629         } else if (!W_ERROR_IS_OK(result)) {
2630                 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2631         }
2632
2633         chan->active_connections++;
2634         *_chan = chan;
2635
2636         return (W_ERROR_IS_OK(result));
2637 }
2638
2639 /****************************************************************
2640  ****************************************************************/
2641
2642 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2643                                                              const struct spoolss_NotifyOption *r)
2644 {
2645         struct spoolss_NotifyOption *option;
2646         uint32_t i,k;
2647
2648         if (!r) {
2649                 return NULL;
2650         }
2651
2652         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2653         if (!option) {
2654                 return NULL;
2655         }
2656
2657         *option = *r;
2658
2659         if (!option->count) {
2660                 return option;
2661         }
2662
2663         option->types = talloc_zero_array(option,
2664                 struct spoolss_NotifyOptionType, option->count);
2665         if (!option->types) {
2666                 talloc_free(option);
2667                 return NULL;
2668         }
2669
2670         for (i=0; i < option->count; i++) {
2671                 option->types[i] = r->types[i];
2672
2673                 if (option->types[i].count) {
2674                         option->types[i].fields = talloc_zero_array(option,
2675                                 union spoolss_Field, option->types[i].count);
2676                         if (!option->types[i].fields) {
2677                                 talloc_free(option);
2678                                 return NULL;
2679                         }
2680                         for (k=0; k<option->types[i].count; k++) {
2681                                 option->types[i].fields[k] =
2682                                         r->types[i].fields[k];
2683                         }
2684                 }
2685         }
2686
2687         return option;
2688 }
2689
2690 /****************************************************************
2691  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2692  *
2693  * before replying OK: status=0 a rpc call is made to the workstation
2694  * asking ReplyOpenPrinter
2695  *
2696  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2697  * called from api_spoolss_rffpcnex
2698 ****************************************************************/
2699
2700 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2701                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2702 {
2703         int snum = -1;
2704         struct spoolss_NotifyOption *option = r->in.notify_options;
2705         struct sockaddr_storage client_ss;
2706
2707         /* store the notify value in the printer struct */
2708
2709         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2710
2711         if (!Printer) {
2712                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2713                         "Invalid handle (%s:%u:%u).\n",
2714                         OUR_HANDLE(r->in.handle)));
2715                 return WERR_BADFID;
2716         }
2717
2718         Printer->notify.flags           = r->in.flags;
2719         Printer->notify.options         = r->in.options;
2720         Printer->notify.printerlocal    = r->in.printer_local;
2721         Printer->notify.msg_ctx         = p->msg_ctx;
2722
2723         TALLOC_FREE(Printer->notify.option);
2724         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2725
2726         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2727
2728         /* Connect to the client machine and send a ReplyOpenPrinter */
2729
2730         if ( Printer->printer_type == SPLHND_SERVER)
2731                 snum = -1;
2732         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2733                         !get_printer_snum(p, r->in.handle, &snum, NULL) )
2734                 return WERR_BADFID;
2735
2736         DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2737                 "client_address is %s\n", p->client_id->addr));
2738
2739         if (!interpret_string_addr(&client_ss, p->client_id->addr,
2740                                    AI_NUMERICHOST)) {
2741                 return WERR_SERVER_UNAVAILABLE;
2742         }
2743
2744         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2745                                         Printer->notify.printerlocal, REG_SZ,
2746                                         &Printer->notify.cli_hnd,
2747                                         &Printer->notify.cli_chan,
2748                                         &client_ss, p->msg_ctx)) {
2749                 return WERR_SERVER_UNAVAILABLE;
2750         }
2751
2752         return WERR_OK;
2753 }
2754
2755 /*******************************************************************
2756  * fill a notify_info_data with the servername
2757  ********************************************************************/
2758
2759 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2760                                        int snum,
2761                                        struct spoolss_Notify *data,
2762                                        print_queue_struct *queue,
2763                                        struct spoolss_PrinterInfo2 *pinfo2,
2764                                        TALLOC_CTX *mem_ctx)
2765 {
2766         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2767 }
2768
2769 /*******************************************************************
2770  * fill a notify_info_data with the printername (not including the servername).
2771  ********************************************************************/
2772
2773 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2774                                         int snum,
2775                                         struct spoolss_Notify *data,
2776                                         print_queue_struct *queue,
2777                                         struct spoolss_PrinterInfo2 *pinfo2,
2778                                         TALLOC_CTX *mem_ctx)
2779 {
2780         /* the notify name should not contain the \\server\ part */
2781         const char *p = strrchr(pinfo2->printername, '\\');
2782
2783         if (!p) {
2784                 p = pinfo2->printername;
2785         } else {
2786                 p++;
2787         }
2788
2789         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2790 }
2791
2792 /*******************************************************************
2793  * fill a notify_info_data with the servicename
2794  ********************************************************************/
2795
2796 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2797                                       int snum,
2798                                       struct spoolss_Notify *data,
2799                                       print_queue_struct *queue,
2800                                       struct spoolss_PrinterInfo2 *pinfo2,
2801                                       TALLOC_CTX *mem_ctx)
2802 {
2803         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2804 }
2805
2806 /*******************************************************************
2807  * fill a notify_info_data with the port name
2808  ********************************************************************/
2809
2810 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2811                                      int snum,
2812                                      struct spoolss_Notify *data,
2813                                      print_queue_struct *queue,
2814                                      struct spoolss_PrinterInfo2 *pinfo2,
2815                                      TALLOC_CTX *mem_ctx)
2816 {
2817         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2818 }
2819
2820 /*******************************************************************
2821  * fill a notify_info_data with the printername
2822  * but it doesn't exist, have to see what to do
2823  ********************************************************************/
2824
2825 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2826                                        int snum,
2827                                        struct spoolss_Notify *data,
2828                                        print_queue_struct *queue,
2829                                        struct spoolss_PrinterInfo2 *pinfo2,
2830                                        TALLOC_CTX *mem_ctx)
2831 {
2832         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2833 }
2834
2835 /*******************************************************************
2836  * fill a notify_info_data with the comment
2837  ********************************************************************/
2838
2839 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2840                                    int snum,
2841                                    struct spoolss_Notify *data,
2842                                    print_queue_struct *queue,
2843                                    struct spoolss_PrinterInfo2 *pinfo2,
2844                                    TALLOC_CTX *mem_ctx)
2845 {
2846         const char *p;
2847
2848         if (*pinfo2->comment == '\0') {
2849                 p = lp_comment(snum);
2850         } else {
2851                 p = pinfo2->comment;
2852         }
2853
2854         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2855 }
2856
2857 /*******************************************************************
2858  * fill a notify_info_data with the comment
2859  * location = "Room 1, floor 2, building 3"
2860  ********************************************************************/
2861
2862 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2863                                     int snum,
2864                                     struct spoolss_Notify *data,
2865                                     print_queue_struct *queue,
2866                                     struct spoolss_PrinterInfo2 *pinfo2,
2867                                     TALLOC_CTX *mem_ctx)
2868 {
2869         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->location);
2870 }
2871
2872 /*******************************************************************
2873  * fill a notify_info_data with the device mode
2874  * jfm:xxxx don't to it for know but that's a real problem !!!
2875  ********************************************************************/
2876
2877 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2878                                    int snum,
2879                                    struct spoolss_Notify *data,
2880                                    print_queue_struct *queue,
2881                                    struct spoolss_PrinterInfo2 *pinfo2,
2882                                    TALLOC_CTX *mem_ctx)
2883 {
2884         /* for a dummy implementation we have to zero the fields */
2885         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2886 }
2887
2888 /*******************************************************************
2889  * fill a notify_info_data with the separator file name
2890  ********************************************************************/
2891
2892 static void spoolss_notify_sepfile(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         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2900 }
2901
2902 /*******************************************************************
2903  * fill a notify_info_data with the print processor
2904  * jfm:xxxx return always winprint to indicate we don't do anything to it
2905  ********************************************************************/
2906
2907 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2908                                            int snum,
2909                                            struct spoolss_Notify *data,
2910                                            print_queue_struct *queue,
2911                                            struct spoolss_PrinterInfo2 *pinfo2,
2912                                            TALLOC_CTX *mem_ctx)
2913 {
2914         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2915 }
2916
2917 /*******************************************************************
2918  * fill a notify_info_data with the print processor options
2919  * jfm:xxxx send an empty string
2920  ********************************************************************/
2921
2922 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2923                                       int snum,
2924                                       struct spoolss_Notify *data,
2925                                       print_queue_struct *queue,
2926                                       struct spoolss_PrinterInfo2 *pinfo2,
2927                                       TALLOC_CTX *mem_ctx)
2928 {
2929         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2930 }
2931
2932 /*******************************************************************
2933  * fill a notify_info_data with the data type
2934  * jfm:xxxx always send RAW as data type
2935  ********************************************************************/
2936
2937 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2938                                     int snum,
2939                                     struct spoolss_Notify *data,
2940                                     print_queue_struct *queue,
2941                                     struct spoolss_PrinterInfo2 *pinfo2,
2942                                     TALLOC_CTX *mem_ctx)
2943 {
2944         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2945 }
2946
2947 /*******************************************************************
2948  * fill a notify_info_data with the security descriptor
2949  * jfm:xxxx send an null pointer to say no security desc
2950  * have to implement security before !
2951  ********************************************************************/
2952
2953 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2954                                          int snum,
2955                                          struct spoolss_Notify *data,
2956                                          print_queue_struct *queue,
2957                                          struct spoolss_PrinterInfo2 *pinfo2,
2958                                          TALLOC_CTX *mem_ctx)
2959 {
2960         SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
2961 }
2962
2963 /*******************************************************************
2964  * fill a notify_info_data with the attributes
2965  * jfm:xxxx a samba printer is always shared
2966  ********************************************************************/
2967
2968 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2969                                       int snum,
2970                                       struct spoolss_Notify *data,
2971                                       print_queue_struct *queue,
2972                                       struct spoolss_PrinterInfo2 *pinfo2,
2973                                       TALLOC_CTX *mem_ctx)
2974 {
2975         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2976 }
2977
2978 /*******************************************************************
2979  * fill a notify_info_data with the priority
2980  ********************************************************************/
2981
2982 static void spoolss_notify_priority(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         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
2990 }
2991
2992 /*******************************************************************
2993  * fill a notify_info_data with the default priority
2994  ********************************************************************/
2995
2996 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
2997                                             int snum,
2998                                             struct spoolss_Notify *data,
2999                                             print_queue_struct *queue,
3000                                             struct spoolss_PrinterInfo2 *pinfo2,
3001                                             TALLOC_CTX *mem_ctx)
3002 {
3003         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
3004 }
3005
3006 /*******************************************************************
3007  * fill a notify_info_data with the start time
3008  ********************************************************************/
3009
3010 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
3011                                       int snum,
3012                                       struct spoolss_Notify *data,
3013                                       print_queue_struct *queue,
3014                                       struct spoolss_PrinterInfo2 *pinfo2,
3015                                       TALLOC_CTX *mem_ctx)
3016 {
3017         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3018 }
3019
3020 /*******************************************************************
3021  * fill a notify_info_data with the until time
3022  ********************************************************************/
3023
3024 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3025                                       int snum,
3026                                       struct spoolss_Notify *data,
3027                                       print_queue_struct *queue,
3028                                       struct spoolss_PrinterInfo2 *pinfo2,
3029                                       TALLOC_CTX *mem_ctx)
3030 {
3031         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3032 }
3033
3034 /*******************************************************************
3035  * fill a notify_info_data with the status
3036  ********************************************************************/
3037
3038 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3039                                   int snum,
3040                                   struct spoolss_Notify *data,
3041                                   print_queue_struct *queue,
3042                                   struct spoolss_PrinterInfo2 *pinfo2,
3043                                   TALLOC_CTX *mem_ctx)
3044 {
3045         print_status_struct status;
3046
3047         print_queue_length(msg_ctx, snum, &status);
3048         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3049 }
3050
3051 /*******************************************************************
3052  * fill a notify_info_data with the number of jobs queued
3053  ********************************************************************/
3054
3055 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3056                                  int snum,
3057                                  struct spoolss_Notify *data,
3058                                  print_queue_struct *queue,
3059                                  struct spoolss_PrinterInfo2 *pinfo2,
3060                                  TALLOC_CTX *mem_ctx)
3061 {
3062         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3063                 data, print_queue_length(msg_ctx, snum, NULL));
3064 }
3065
3066 /*******************************************************************
3067  * fill a notify_info_data with the average ppm
3068  ********************************************************************/
3069
3070 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3071                                        int snum,
3072                                        struct spoolss_Notify *data,
3073                                        print_queue_struct *queue,
3074                                        struct spoolss_PrinterInfo2 *pinfo2,
3075                                        TALLOC_CTX *mem_ctx)
3076 {
3077         /* always respond 8 pages per minutes */
3078         /* a little hard ! */
3079         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3080 }
3081
3082 /*******************************************************************
3083  * fill a notify_info_data with username
3084  ********************************************************************/
3085
3086 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3087                                     int snum,
3088                                     struct spoolss_Notify *data,
3089                                     print_queue_struct *queue,
3090                                     struct spoolss_PrinterInfo2 *pinfo2,
3091                                     TALLOC_CTX *mem_ctx)
3092 {
3093         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3094 }
3095
3096 /*******************************************************************
3097  * fill a notify_info_data with job status
3098  ********************************************************************/
3099
3100 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3101                                       int snum,
3102                                       struct spoolss_Notify *data,
3103                                       print_queue_struct *queue,
3104                                       struct spoolss_PrinterInfo2 *pinfo2,
3105                                       TALLOC_CTX *mem_ctx)
3106 {
3107         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3108 }
3109
3110 /*******************************************************************
3111  * fill a notify_info_data with job name
3112  ********************************************************************/
3113
3114 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3115                                     int snum,
3116                                     struct spoolss_Notify *data,
3117                                     print_queue_struct *queue,
3118                                     struct spoolss_PrinterInfo2 *pinfo2,
3119                                     TALLOC_CTX *mem_ctx)
3120 {
3121         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3122 }
3123
3124 /*******************************************************************
3125  * fill a notify_info_data with job status
3126  ********************************************************************/
3127
3128 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3129                                              int snum,
3130                                              struct spoolss_Notify *data,
3131                                              print_queue_struct *queue,
3132                                              struct spoolss_PrinterInfo2 *pinfo2,
3133                                              TALLOC_CTX *mem_ctx)
3134 {
3135         /*
3136          * Now we're returning job status codes we just return a "" here. JRA.
3137          */
3138
3139         const char *p = "";
3140
3141 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3142         p = "unknown";
3143
3144         switch (queue->status) {
3145         case LPQ_QUEUED:
3146                 p = "Queued";
3147                 break;
3148         case LPQ_PAUSED:
3149                 p = "";    /* NT provides the paused string */
3150                 break;
3151         case LPQ_SPOOLING:
3152                 p = "Spooling";
3153                 break;
3154         case LPQ_PRINTING:
3155                 p = "Printing";
3156                 break;
3157         }
3158 #endif /* NO LONGER NEEDED. */
3159
3160         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3161 }
3162
3163 /*******************************************************************
3164  * fill a notify_info_data with job time
3165  ********************************************************************/
3166
3167 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3168                                     int snum,
3169                                     struct spoolss_Notify *data,
3170                                     print_queue_struct *queue,
3171                                     struct spoolss_PrinterInfo2 *pinfo2,
3172                                     TALLOC_CTX *mem_ctx)
3173 {
3174         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3175 }
3176
3177 /*******************************************************************
3178  * fill a notify_info_data with job size
3179  ********************************************************************/
3180
3181 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3182                                     int snum,
3183                                     struct spoolss_Notify *data,
3184                                     print_queue_struct *queue,
3185                                     struct spoolss_PrinterInfo2 *pinfo2,
3186                                     TALLOC_CTX *mem_ctx)
3187 {
3188         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3189 }
3190
3191 /*******************************************************************
3192  * fill a notify_info_data with page info
3193  ********************************************************************/
3194 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3195                                        int snum,
3196                                 struct spoolss_Notify *data,
3197                                 print_queue_struct *queue,
3198                                 struct spoolss_PrinterInfo2 *pinfo2,
3199                                 TALLOC_CTX *mem_ctx)
3200 {
3201         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3202 }
3203
3204 /*******************************************************************
3205  * fill a notify_info_data with pages printed info.
3206  ********************************************************************/
3207 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3208                                          int snum,
3209                                 struct spoolss_Notify *data,
3210                                 print_queue_struct *queue,
3211                                 struct spoolss_PrinterInfo2 *pinfo2,
3212                                 TALLOC_CTX *mem_ctx)
3213 {
3214         /* Add code when back-end tracks this */
3215         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3216 }
3217
3218 /*******************************************************************
3219  Fill a notify_info_data with job position.
3220  ********************************************************************/
3221
3222 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3223                                         int snum,
3224                                         struct spoolss_Notify *data,
3225                                         print_queue_struct *queue,
3226                                         struct spoolss_PrinterInfo2 *pinfo2,
3227                                         TALLOC_CTX *mem_ctx)
3228 {
3229         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3230 }
3231
3232 /*******************************************************************
3233  Fill a notify_info_data with submitted time.
3234  ********************************************************************/
3235
3236 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3237                                           int snum,
3238                                           struct spoolss_Notify *data,
3239                                           print_queue_struct *queue,
3240                                           struct spoolss_PrinterInfo2 *pinfo2,
3241                                           TALLOC_CTX *mem_ctx)
3242 {
3243         data->data.string.string = NULL;
3244         data->data.string.size = 0;
3245
3246         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3247                                &data->data.string.string,
3248                                &data->data.string.size);
3249
3250 }
3251
3252 struct s_notify_info_data_table
3253 {
3254         enum spoolss_NotifyType type;
3255         uint16_t field;
3256         const char *name;
3257         enum spoolss_NotifyTable variable_type;
3258         void (*fn) (struct messaging_context *msg_ctx,
3259                     int snum, struct spoolss_Notify *data,
3260                     print_queue_struct *queue,
3261                     struct spoolss_PrinterInfo2 *pinfo2,
3262                     TALLOC_CTX *mem_ctx);
3263 };
3264
3265 /* A table describing the various print notification constants and
3266    whether the notification data is a pointer to a variable sized
3267    buffer, a one value uint32_t or a two value uint32_t. */
3268
3269 static const struct s_notify_info_data_table notify_info_data_table[] =
3270 {
3271 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME,         "PRINTER_NOTIFY_FIELD_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3272 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME,        "PRINTER_NOTIFY_FIELD_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3273 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME,          "PRINTER_NOTIFY_FIELD_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
3274 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME,           "PRINTER_NOTIFY_FIELD_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3275 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME,         "PRINTER_NOTIFY_FIELD_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3276 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT,             "PRINTER_NOTIFY_FIELD_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
3277 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION,            "PRINTER_NOTIFY_FIELD_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
3278 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE,             "PRINTER_NOTIFY_FIELD_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3279 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE,             "PRINTER_NOTIFY_FIELD_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
3280 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR,     "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3281 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS,          "PRINTER_NOTIFY_FIELD_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3282 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE,            "PRINTER_NOTIFY_FIELD_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3283 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
3284 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES,          "PRINTER_NOTIFY_FIELD_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
3285 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY,            "PRINTER_NOTIFY_FIELD_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3286 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
3287 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME,          "PRINTER_NOTIFY_FIELD_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3288 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME,          "PRINTER_NOTIFY_FIELD_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3289 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS,              "PRINTER_NOTIFY_FIELD_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
3290 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING,       "PRINTER_NOTIFY_FIELD_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
3291 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS,               "PRINTER_NOTIFY_FIELD_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
3292 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM,         "PRINTER_NOTIFY_FIELD_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
3293 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES,         "PRINTER_NOTIFY_FIELD_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
3294 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED,       "PRINTER_NOTIFY_FIELD_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3295 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES,         "PRINTER_NOTIFY_FIELD_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
3296 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED,       "PRINTER_NOTIFY_FIELD_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3297 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINTER_NAME,            "JOB_NOTIFY_FIELD_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3298 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_MACHINE_NAME,            "JOB_NOTIFY_FIELD_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3299 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PORT_NAME,               "JOB_NOTIFY_FIELD_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3300 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_USER_NAME,               "JOB_NOTIFY_FIELD_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
3301 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_NOTIFY_NAME,             "JOB_NOTIFY_FIELD_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
3302 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DATATYPE,                "JOB_NOTIFY_FIELD_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3303 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINT_PROCESSOR,         "JOB_NOTIFY_FIELD_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3304 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PARAMETERS,              "JOB_NOTIFY_FIELD_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3305 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DRIVER_NAME,             "JOB_NOTIFY_FIELD_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3306 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DEVMODE,                 "JOB_NOTIFY_FIELD_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3307 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS,                  "JOB_NOTIFY_FIELD_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
3308 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS_STRING,           "JOB_NOTIFY_FIELD_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
3309 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
3310 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DOCUMENT,                "JOB_NOTIFY_FIELD_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
3311 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRIORITY,                "JOB_NOTIFY_FIELD_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3312 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_POSITION,                "JOB_NOTIFY_FIELD_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
3313 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SUBMITTED,               "JOB_NOTIFY_FIELD_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
3314 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_START_TIME,              "JOB_NOTIFY_FIELD_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3315 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_UNTIL_TIME,              "JOB_NOTIFY_FIELD_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3316 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TIME,                    "JOB_NOTIFY_FIELD_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
3317 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_PAGES,             "JOB_NOTIFY_FIELD_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
3318 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PAGES_PRINTED,           "JOB_NOTIFY_FIELD_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
3319 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_BYTES,             "JOB_NOTIFY_FIELD_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
3320 };
3321
3322 /*******************************************************************
3323  Return the variable_type of info_data structure.
3324 ********************************************************************/
3325
3326 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3327                                                                   uint16_t field)
3328 {
3329         int i=0;
3330
3331         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3332                 if ( (notify_info_data_table[i].type == type) &&
3333                      (notify_info_data_table[i].field == field) ) {
3334                         return notify_info_data_table[i].variable_type;
3335                 }
3336         }
3337
3338         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3339
3340         return (enum spoolss_NotifyTable) 0;
3341 }
3342
3343 /****************************************************************************
3344 ****************************************************************************/
3345
3346 static bool search_notify(enum spoolss_NotifyType type,
3347                           uint16_t field,
3348                           int *value)
3349 {
3350         int i;
3351
3352         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3353                 if (notify_info_data_table[i].type == type &&
3354                     notify_info_data_table[i].field == field &&
3355                     notify_info_data_table[i].fn != NULL) {
3356                         *value = i;
3357                         return true;
3358                 }
3359         }
3360
3361         return false;
3362 }
3363
3364 /****************************************************************************
3365 ****************************************************************************/
3366
3367 static void construct_info_data(struct spoolss_Notify *info_data,
3368                                 enum spoolss_NotifyType type,
3369                                 uint16_t field, int id)
3370 {
3371         info_data->type                 = type;
3372         info_data->field.field          = field;
3373         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3374         info_data->job_id               = id;
3375 }
3376
3377 /*******************************************************************
3378  *
3379  * fill a notify_info struct with info asked
3380  *
3381  ********************************************************************/
3382
3383 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3384                                           struct printer_handle *print_hnd,
3385                                           struct spoolss_NotifyInfo *info,
3386                                           struct spoolss_PrinterInfo2 *pinfo2,
3387                                           int snum,
3388                                           const struct spoolss_NotifyOptionType *option_type,
3389                                           uint32_t id,
3390                                           TALLOC_CTX *mem_ctx)
3391 {
3392         int field_num,j;
3393         enum spoolss_NotifyType type;
3394         uint16_t field;
3395
3396         struct spoolss_Notify *current_data;
3397         print_queue_struct *queue=NULL;
3398
3399         type = option_type->type;
3400
3401         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3402                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3403                 option_type->count, lp_servicename(snum)));
3404
3405         for(field_num=0; field_num < option_type->count; field_num++) {
3406                 field = option_type->fields[field_num].field;
3407
3408                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3409
3410                 if (!search_notify(type, field, &j) )
3411                         continue;
3412
3413                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3414                                                       struct spoolss_Notify,
3415                                                       info->count + 1);
3416                 if (info->notifies == NULL) {
3417                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3418                         return false;
3419                 }
3420
3421                 current_data = &info->notifies[info->count];
3422
3423                 construct_info_data(current_data, type, field, id);
3424
3425                 DEBUG(10, ("construct_notify_printer_info: "
3426                            "calling [%s]  snum=%d  printername=[%s])\n",
3427                            notify_info_data_table[j].name, snum,
3428                            pinfo2->printername));
3429
3430                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3431                                              queue, pinfo2, mem_ctx);
3432
3433                 info->count++;
3434         }
3435
3436         return true;
3437 }
3438
3439 /*******************************************************************
3440  *
3441  * fill a notify_info struct with info asked
3442  *
3443  ********************************************************************/
3444
3445 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3446                                        print_queue_struct *queue,
3447                                        struct spoolss_NotifyInfo *info,
3448                                        struct spoolss_PrinterInfo2 *pinfo2,
3449                                        int snum,
3450                                        const struct spoolss_NotifyOptionType *option_type,
3451                                        uint32_t id,
3452                                        TALLOC_CTX *mem_ctx)
3453 {
3454         int field_num,j;
3455         enum spoolss_NotifyType type;
3456         uint16_t field;
3457         struct spoolss_Notify *current_data;
3458
3459         DEBUG(4,("construct_notify_jobs_info\n"));
3460
3461         type = option_type->type;
3462
3463         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3464                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3465                 option_type->count));
3466
3467         for(field_num=0; field_num<option_type->count; field_num++) {
3468                 field = option_type->fields[field_num].field;
3469
3470                 if (!search_notify(type, field, &j) )
3471                         continue;
3472
3473                 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3474                                                       struct spoolss_Notify,
3475                                                       info->count + 1);
3476                 if (info->notifies == NULL) {
3477                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3478                         return false;
3479                 }
3480
3481                 current_data=&(info->notifies[info->count]);
3482
3483                 construct_info_data(current_data, type, field, id);
3484                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3485                                              queue, pinfo2, mem_ctx);
3486                 info->count++;
3487         }
3488
3489         return true;
3490 }
3491
3492 /*
3493  * JFM: The enumeration is not that simple, it's even non obvious.
3494  *
3495  * let's take an example: I want to monitor the PRINTER SERVER for
3496  * the printer's name and the number of jobs currently queued.
3497  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3498  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3499  *
3500  * I have 3 printers on the back of my server.
3501  *
3502  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3503  * structures.
3504  *   Number     Data                    Id
3505  *      1       printer 1 name          1
3506  *      2       printer 1 cjob          1
3507  *      3       printer 2 name          2
3508  *      4       printer 2 cjob          2
3509  *      5       printer 3 name          3
3510  *      6       printer 3 name          3
3511  *
3512  * that's the print server case, the printer case is even worse.
3513  */
3514
3515 /*******************************************************************
3516  *
3517  * enumerate all printers on the printserver
3518  * fill a notify_info struct with info asked
3519  *
3520  ********************************************************************/
3521
3522 static WERROR printserver_notify_info(struct pipes_struct *p,
3523                                       struct policy_handle *hnd,
3524                                       struct spoolss_NotifyInfo *info,
3525                                       TALLOC_CTX *mem_ctx)
3526 {
3527         int snum;
3528         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3529         int n_services=lp_numservices();
3530         int i;
3531         struct spoolss_NotifyOption *option;
3532         struct spoolss_NotifyOptionType option_type;
3533         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3534         WERROR result;
3535
3536         DEBUG(4,("printserver_notify_info\n"));
3537
3538         if (!Printer)
3539                 return WERR_BADFID;
3540
3541         option = Printer->notify.option;
3542
3543         info->version   = 2;
3544         info->notifies  = NULL;
3545         info->count     = 0;
3546
3547         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3548            sending a ffpcn() request first */
3549
3550         if ( !option )
3551                 return WERR_BADFID;
3552
3553         for (i=0; i<option->count; i++) {
3554                 option_type = option->types[i];
3555
3556                 if (option_type.type != PRINTER_NOTIFY_TYPE)
3557                         continue;
3558
3559                 for (snum = 0; snum < n_services; snum++) {
3560                         if (!lp_browseable(snum) ||
3561                             !lp_snum_ok(snum) ||
3562                             !lp_print_ok(snum)) {
3563                                 continue; /* skip */
3564                         }
3565
3566                         /* Maybe we should use the SYSTEM session_info here... */
3567                         result = winreg_get_printer(mem_ctx,
3568                                                     get_session_info_system(),
3569                                                     p->msg_ctx,
3570                                                     lp_servicename(snum),
3571                                                     &pinfo2);
3572                         if (!W_ERROR_IS_OK(result)) {
3573                                 DEBUG(4, ("printserver_notify_info: "
3574                                           "Failed to get printer [%s]\n",
3575                                           lp_servicename(snum)));
3576                                 continue;
3577                         }
3578
3579
3580                         construct_notify_printer_info(p->msg_ctx,
3581                                                       Printer, info,
3582                                                       pinfo2, snum,
3583                                                       &option_type, snum,
3584                                                       mem_ctx);
3585
3586                         TALLOC_FREE(pinfo2);
3587                 }
3588         }
3589
3590 #if 0
3591         /*
3592          * Debugging information, don't delete.
3593          */
3594
3595         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3596         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3597         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3598
3599         for (i=0; i<info->count; i++) {
3600                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3601                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3602                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3603         }
3604 #endif
3605
3606         return WERR_OK;
3607 }
3608
3609 /*******************************************************************
3610  *
3611  * fill a notify_info struct with info asked
3612  *
3613  ********************************************************************/
3614
3615 static WERROR printer_notify_info(struct pipes_struct *p,
3616                                   struct policy_handle *hnd,
3617                                   struct spoolss_NotifyInfo *info,
3618                                   TALLOC_CTX *mem_ctx)
3619 {
3620         int snum;
3621         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3622         int i;
3623         uint32_t id;
3624         struct spoolss_NotifyOption *option;
3625         struct spoolss_NotifyOptionType option_type;
3626         int count,j;
3627         print_queue_struct *queue=NULL;
3628         print_status_struct status;
3629         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3630         WERROR result;
3631
3632         DEBUG(4,("printer_notify_info\n"));
3633
3634         if (!Printer)
3635                 return WERR_BADFID;
3636
3637         option = Printer->notify.option;
3638         id = 0x0;
3639
3640         info->version   = 2;
3641         info->notifies  = NULL;
3642         info->count     = 0;
3643
3644         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3645            sending a ffpcn() request first */
3646
3647         if ( !option )
3648                 return WERR_BADFID;
3649
3650         get_printer_snum(p, hnd, &snum, NULL);
3651
3652         /* Maybe we should use the SYSTEM session_info here... */
3653         result = winreg_get_printer(mem_ctx,
3654                                     get_session_info_system(),
3655                                     p->msg_ctx,
3656                                     lp_servicename(snum), &pinfo2);
3657         if (!W_ERROR_IS_OK(result)) {
3658                 return WERR_BADFID;
3659         }
3660
3661         for (i=0; i<option->count; i++) {
3662                 option_type = option->types[i];
3663
3664                 switch (option_type.type) {
3665                 case PRINTER_NOTIFY_TYPE:
3666                         if (construct_notify_printer_info(p->msg_ctx,
3667                                                           Printer, info,
3668                                                           pinfo2, snum,
3669                                                           &option_type, id,
3670                                                           mem_ctx)) {
3671                                 id--;
3672                         }
3673                         break;
3674
3675                 case JOB_NOTIFY_TYPE:
3676
3677                         count = print_queue_status(p->msg_ctx, snum, &queue,
3678                                                    &status);
3679
3680                         for (j=0; j<count; j++) {
3681                                 construct_notify_jobs_info(p->msg_ctx,
3682                                                            &queue[j], info,
3683                                                            pinfo2, snum,
3684                                                            &option_type,
3685                                                            queue[j].job,
3686                                                            mem_ctx);
3687                         }
3688
3689                         SAFE_FREE(queue);
3690                         break;
3691                 }
3692         }
3693
3694         /*
3695          * Debugging information, don't delete.
3696          */
3697         /*
3698         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3699         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3700         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3701
3702         for (i=0; i<info->count; i++) {
3703                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3704                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3705                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3706         }
3707         */
3708
3709         talloc_free(pinfo2);
3710         return WERR_OK;
3711 }
3712
3713 /****************************************************************
3714  _spoolss_RouterRefreshPrinterChangeNotify
3715 ****************************************************************/
3716
3717 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3718                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3719 {
3720         struct spoolss_NotifyInfo *info;
3721
3722         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3723         WERROR result = WERR_BADFID;
3724
3725         /* we always have a spoolss_NotifyInfo struct */
3726         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3727         if (!info) {
3728                 result = WERR_NOMEM;
3729                 goto done;
3730         }
3731
3732         *r->out.info = info;
3733
3734         if (!Printer) {
3735                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3736                         "Invalid handle (%s:%u:%u).\n",
3737                         OUR_HANDLE(r->in.handle)));
3738                 goto done;
3739         }
3740
3741         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3742
3743         /*
3744          *      We are now using the change value, and
3745          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3746          *      I don't have a global notification system, I'm sending back all the
3747          *      information even when _NOTHING_ has changed.
3748          */
3749
3750         /* We need to keep track of the change value to send back in
3751            RRPCN replies otherwise our updates are ignored. */
3752
3753         Printer->notify.fnpcn = true;
3754
3755         if (Printer->notify.cli_chan != NULL &&
3756             Printer->notify.cli_chan->active_connections > 0) {
3757                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3758                         "Saving change value in request [%x]\n",
3759                         r->in.change_low));
3760                 Printer->notify.change = r->in.change_low;
3761         }
3762
3763         /* just ignore the spoolss_NotifyOption */
3764
3765         switch (Printer->printer_type) {
3766                 case SPLHND_SERVER:
3767                         result = printserver_notify_info(p, r->in.handle,
3768                                                          info, p->mem_ctx);
3769                         break;
3770
3771                 case SPLHND_PRINTER:
3772                         result = printer_notify_info(p, r->in.handle,
3773                                                      info, p->mem_ctx);
3774                         break;
3775         }
3776
3777         Printer->notify.fnpcn = false;
3778
3779 done:
3780         return result;
3781 }
3782
3783 /********************************************************************
3784  ********************************************************************/
3785
3786 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3787                                  const char *servername,
3788                                  const char *printername,
3789                                  const char **printername_p)
3790 {
3791         /* FIXME: add lp_force_printername() */
3792
3793         if (servername == NULL) {
3794                 *printername_p = talloc_strdup(mem_ctx, printername);
3795                 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3796                 return WERR_OK;
3797         }
3798
3799         if (servername[0] == '\\' && servername[1] == '\\') {
3800                 servername += 2;
3801         }
3802
3803         *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3804         W_ERROR_HAVE_NO_MEMORY(*printername_p);
3805
3806         return WERR_OK;
3807 }
3808
3809 /********************************************************************
3810  ********************************************************************/
3811
3812 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3813                                           const char *printername)
3814 {
3815         if (dm == NULL) {
3816                 return;
3817         }
3818
3819         dm->devicename = talloc_strndup(dm, printername,
3820                                         MIN(strlen(printername), 31));
3821 }
3822
3823 /********************************************************************
3824  * construct_printer_info_0
3825  * fill a printer_info_0 struct
3826  ********************************************************************/
3827
3828 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3829                                       const struct auth_serversupplied_info *session_info,
3830                                       struct messaging_context *msg_ctx,
3831                                       struct spoolss_PrinterInfo2 *info2,
3832                                       const char *servername,
3833                                       struct spoolss_PrinterInfo0 *r,
3834                                       int snum)
3835 {
3836         int count;
3837         struct printer_session_counter *session_counter;
3838         struct timeval setuptime;
3839         print_status_struct status;
3840         WERROR result;
3841
3842         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3843         if (!W_ERROR_IS_OK(result)) {
3844                 return result;
3845         }
3846
3847         if (servername) {
3848                 r->servername = talloc_strdup(mem_ctx, servername);
3849                 W_ERROR_HAVE_NO_MEMORY(r->servername);
3850         } else {
3851                 r->servername = NULL;
3852         }
3853
3854         count = print_queue_length(msg_ctx, snum, &status);
3855
3856         /* check if we already have a counter for this printer */
3857         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3858                 if (session_counter->snum == snum)
3859                         break;
3860         }
3861
3862         /* it's the first time, add it to the list */
3863         if (session_counter == NULL) {
3864                 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3865                 W_ERROR_HAVE_NO_MEMORY(session_counter);
3866                 session_counter->snum           = snum;
3867                 session_counter->counter        = 0;
3868                 DLIST_ADD(counter_list, session_counter);
3869         }
3870
3871         /* increment it */
3872         session_counter->counter++;
3873
3874         r->cjobs                        = count;
3875         r->total_jobs                   = 0;
3876         r->total_bytes                  = 0;
3877
3878         get_startup_time(&setuptime);
3879         init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3880
3881         /* JFM:
3882          * the global_counter should be stored in a TDB as it's common to all the clients
3883          * and should be zeroed on samba startup
3884          */
3885         r->global_counter               = session_counter->counter;
3886         r->total_pages                  = 0;
3887         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3888         SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3889         SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3890         r->free_build                   = SPOOLSS_RELEASE_BUILD;
3891         r->spooling                     = 0;
3892         r->max_spooling                 = 0;
3893         r->session_counter              = session_counter->counter;
3894         r->num_error_out_of_paper       = 0x0;
3895         r->num_error_not_ready          = 0x0;          /* number of print failure */
3896         r->job_error                    = 0x0;
3897         r->number_of_processors         = 0x1;
3898         r->processor_type               = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3899         r->high_part_total_bytes        = 0x0;
3900
3901         /* ChangeID in milliseconds*/
3902         winreg_printer_get_changeid(mem_ctx, session_info, msg_ctx,
3903                                     info2->sharename, &r->change_id);
3904
3905         r->last_error                   = WERR_OK;
3906         r->status                       = nt_printq_status(status.status);
3907         r->enumerate_network_printers   = 0x0;
3908         r->c_setprinter                 = 0x0;
3909         r->processor_architecture       = PROCESSOR_ARCHITECTURE_INTEL;
3910         r->processor_level              = 0x6;          /* 6  ???*/
3911         r->ref_ic                       = 0;
3912         r->reserved2                    = 0;
3913         r->reserved3                    = 0;
3914
3915         return WERR_OK;
3916 }
3917
3918
3919 /********************************************************************
3920  * construct_printer_info1
3921  * fill a spoolss_PrinterInfo1 struct
3922 ********************************************************************/
3923
3924 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3925                                       const struct spoolss_PrinterInfo2 *info2,
3926                                       uint32_t flags,
3927                                       const char *servername,
3928                                       struct spoolss_PrinterInfo1 *r,
3929                                       int snum)
3930 {
3931         WERROR result;
3932
3933         r->flags                = flags;
3934
3935         if (info2->comment == NULL || info2->comment[0] == '\0') {
3936                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
3937         } else {
3938                 r->comment      = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3939         }
3940         W_ERROR_HAVE_NO_MEMORY(r->comment);
3941
3942         result = create_printername(mem_ctx, servername, info2->printername, &r->name);
3943         if (!W_ERROR_IS_OK(result)) {
3944                 return result;
3945         }
3946
3947         r->description          = talloc_asprintf(mem_ctx, "%s,%s,%s",
3948                                                   r->name,
3949                                                   info2->drivername,
3950                                                   r->comment);
3951         W_ERROR_HAVE_NO_MEMORY(r->description);
3952
3953         return WERR_OK;
3954 }
3955
3956 /********************************************************************
3957  * construct_printer_info2
3958  * fill a spoolss_PrinterInfo2 struct
3959 ********************************************************************/
3960
3961 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3962                                       struct messaging_context *msg_ctx,
3963                                       const struct spoolss_PrinterInfo2 *info2,
3964                                       const char *servername,
3965                                       struct spoolss_PrinterInfo2 *r,
3966                                       int snum)
3967 {
3968         int count;
3969         print_status_struct status;
3970         WERROR result;
3971
3972         count = print_queue_length(msg_ctx, snum, &status);
3973
3974         if (servername) {
3975                 r->servername           = talloc_strdup(mem_ctx, servername);
3976                 W_ERROR_HAVE_NO_MEMORY(r->servername);
3977         } else {
3978                 r->servername           = NULL;
3979         }
3980
3981         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3982         if (!W_ERROR_IS_OK(result)) {
3983                 return result;
3984         }
3985
3986         r->sharename            = talloc_strdup(mem_ctx, lp_servicename(snum));
3987         W_ERROR_HAVE_NO_MEMORY(r->sharename);
3988         r->portname             = talloc_strdup(mem_ctx, info2->portname);
3989         W_ERROR_HAVE_NO_MEMORY(r->portname);
3990         r->drivername           = talloc_strdup(mem_ctx, info2->drivername);
3991         W_ERROR_HAVE_NO_MEMORY(r->drivername);
3992
3993         if (info2->comment[0] == '\0') {
3994                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
3995         } else {
3996                 r->comment      = talloc_strdup(mem_ctx, info2->comment);
3997         }
3998         W_ERROR_HAVE_NO_MEMORY(r->comment);
3999
4000         r->location             = talloc_strdup(mem_ctx, info2->location);
4001         W_ERROR_HAVE_NO_MEMORY(r->location);
4002         r->sepfile              = talloc_strdup(mem_ctx, info2->sepfile);
4003         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4004         r->printprocessor       = talloc_strdup(mem_ctx, info2->printprocessor);
4005         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4006         r->datatype             = talloc_strdup(mem_ctx, info2->datatype);
4007         W_ERROR_HAVE_NO_MEMORY(r->datatype);
4008         r->parameters           = talloc_strdup(mem_ctx, info2->parameters);
4009         W_ERROR_HAVE_NO_MEMORY(r->parameters);
4010
4011         r->attributes           = info2->attributes;
4012
4013         r->priority             = info2->priority;
4014         r->defaultpriority      = info2->defaultpriority;
4015         r->starttime            = info2->starttime;
4016         r->untiltime            = info2->untiltime;
4017         r->status               = nt_printq_status(status.status);
4018         r->cjobs                = count;
4019         r->averageppm           = info2->averageppm;
4020
4021         copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4022         if (!r->devmode) {
4023                 DEBUG(8,("Returning NULL Devicemode!\n"));
4024         }
4025
4026         compose_devicemode_devicename(r->devmode, r->printername);
4027
4028         r->secdesc = NULL;
4029
4030         if (info2->secdesc != NULL) {
4031                 /* don't use talloc_steal() here unless you do a deep steal of all
4032                    the SEC_DESC members */
4033
4034                 r->secdesc      = dup_sec_desc(mem_ctx, info2->secdesc);
4035         }
4036
4037         return WERR_OK;
4038 }
4039
4040 /********************************************************************
4041  * construct_printer_info3
4042  * fill a spoolss_PrinterInfo3 struct
4043  ********************************************************************/
4044
4045 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4046                                       const struct spoolss_PrinterInfo2 *info2,
4047                                       const char *servername,
4048                                       struct spoolss_PrinterInfo3 *r,
4049                                       int snum)
4050 {
4051         /* These are the components of the SD we are returning. */
4052
4053         if (info2->secdesc != NULL) {
4054                 /* don't use talloc_steal() here unless you do a deep steal of all
4055                    the SEC_DESC members */
4056
4057                 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4058                 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
4059         }
4060
4061         return WERR_OK;
4062 }
4063
4064 /********************************************************************
4065  * construct_printer_info4
4066  * fill a spoolss_PrinterInfo4 struct
4067  ********************************************************************/
4068
4069 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4070                                       const struct spoolss_PrinterInfo2 *info2,
4071                                       const char *servername,
4072                                       struct spoolss_PrinterInfo4 *r,
4073                                       int snum)
4074 {
4075         WERROR result;
4076
4077         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4078         if (!W_ERROR_IS_OK(result)) {
4079                 return result;
4080         }
4081
4082         if (servername) {
4083                 r->servername   = talloc_strdup(mem_ctx, servername);
4084                 W_ERROR_HAVE_NO_MEMORY(r->servername);
4085         } else {
4086                 r->servername = NULL;
4087         }
4088
4089         r->attributes   = info2->attributes;
4090
4091         return WERR_OK;
4092 }
4093
4094 /********************************************************************
4095  * construct_printer_info5
4096  * fill a spoolss_PrinterInfo5 struct
4097  ********************************************************************/
4098
4099 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4100                                       const struct spoolss_PrinterInfo2 *info2,
4101                                       const char *servername,
4102                                       struct spoolss_PrinterInfo5 *r,
4103                                       int snum)
4104 {
4105         WERROR result;
4106
4107         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4108         if (!W_ERROR_IS_OK(result)) {
4109                 return result;
4110         }
4111
4112         r->portname     = talloc_strdup(mem_ctx, info2->portname);
4113         W_ERROR_HAVE_NO_MEMORY(r->portname);
4114
4115         r->attributes   = info2->attributes;
4116
4117         /* these two are not used by NT+ according to MSDN */
4118         r->device_not_selected_timeout          = 0x0;  /* have seen 0x3a98 */
4119         r->transmission_retry_timeout           = 0x0;  /* have seen 0xafc8 */
4120
4121         return WERR_OK;
4122 }
4123
4124 /********************************************************************
4125  * construct_printer_info_6
4126  * fill a spoolss_PrinterInfo6 struct
4127  ********************************************************************/
4128
4129 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4130                                       struct messaging_context *msg_ctx,
4131                                       const struct spoolss_PrinterInfo2 *info2,
4132                                       const char *servername,
4133                                       struct spoolss_PrinterInfo6 *r,
4134                                       int snum)
4135 {
4136         int count;
4137         print_status_struct status;
4138
4139         count = print_queue_length(msg_ctx, snum, &status);
4140
4141         r->status = nt_printq_status(status.status);
4142
4143         return WERR_OK;
4144 }
4145
4146 /********************************************************************
4147  * construct_printer_info7
4148  * fill a spoolss_PrinterInfo7 struct
4149  ********************************************************************/
4150
4151 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4152                                       struct messaging_context *msg_ctx,
4153                                       const char *servername,
4154                                       struct spoolss_PrinterInfo7 *r,
4155                                       int snum)
4156 {
4157         struct auth_serversupplied_info *session_info;
4158         struct GUID guid;
4159         NTSTATUS status;
4160
4161         status = make_session_info_system(mem_ctx, &session_info);
4162         if (!NT_STATUS_IS_OK(status)) {
4163                 DEBUG(0, ("construct_printer_info7: "
4164                           "Could not create system session_info\n"));
4165                 return WERR_NOMEM;
4166         }
4167
4168         if (is_printer_published(mem_ctx, session_info, msg_ctx,
4169                                  servername,
4170                                  lp_servicename(snum), &guid, NULL)) {
4171                 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4172                 r->action = DSPRINT_PUBLISH;
4173         } else {
4174                 r->guid = talloc_strdup(mem_ctx, "");
4175                 r->action = DSPRINT_UNPUBLISH;
4176         }
4177         W_ERROR_HAVE_NO_MEMORY(r->guid);
4178
4179         TALLOC_FREE(session_info);
4180         return WERR_OK;
4181 }
4182
4183 /********************************************************************
4184  * construct_printer_info8
4185  * fill a spoolss_PrinterInfo8 struct
4186  ********************************************************************/
4187
4188 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4189                                       const struct spoolss_PrinterInfo2 *info2,
4190                                       const char *servername,
4191                                       struct spoolss_DeviceModeInfo *r,
4192                                       int snum)
4193 {
4194         WERROR result;
4195         const char *printername;
4196
4197         result = create_printername(mem_ctx, servername, info2->printername, &printername);
4198         if (!W_ERROR_IS_OK(result)) {
4199                 return result;
4200         }
4201
4202         copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4203         if (!r->devmode) {
4204                 DEBUG(8,("Returning NULL Devicemode!\n"));
4205         }
4206
4207         compose_devicemode_devicename(r->devmode, printername);
4208
4209         return WERR_OK;
4210 }
4211
4212
4213 /********************************************************************
4214 ********************************************************************/
4215
4216 static bool snum_is_shared_printer(int snum)
4217 {
4218         return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4219 }
4220
4221 /********************************************************************
4222  Spoolss_enumprinters.
4223 ********************************************************************/
4224
4225 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4226                                            const struct auth_serversupplied_info *session_info,
4227                                            struct messaging_context *msg_ctx,
4228                                            const char *servername,
4229                                            uint32_t level,
4230                                            uint32_t flags,
4231                                            union spoolss_PrinterInfo **info_p,
4232                                            uint32_t *count_p)
4233 {
4234         int snum;
4235         int n_services = lp_numservices();
4236         union spoolss_PrinterInfo *info = NULL;
4237         uint32_t count = 0;
4238         WERROR result = WERR_OK;
4239
4240         *count_p = 0;
4241         *info_p = NULL;
4242
4243         for (snum = 0; snum < n_services; snum++) {
4244
4245                 const char *printer;
4246                 struct spoolss_PrinterInfo2 *info2;
4247
4248                 if (!snum_is_shared_printer(snum)) {
4249                         continue;
4250                 }
4251
4252                 printer = lp_const_servicename(snum);
4253
4254                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4255                         printer, snum));
4256
4257                 result = winreg_create_printer(mem_ctx,
4258                                                session_info,
4259                                                msg_ctx,
4260                                                printer);
4261                 if (!W_ERROR_IS_OK(result)) {
4262                         goto out;
4263                 }
4264
4265                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4266                                             union spoolss_PrinterInfo,
4267                                             count + 1);
4268                 if (!info) {
4269                         result = WERR_NOMEM;
4270                         goto out;
4271                 }
4272
4273                 result = winreg_get_printer(mem_ctx, session_info, msg_ctx,
4274                                             printer, &info2);
4275                 if (!W_ERROR_IS_OK(result)) {
4276                         goto out;
4277                 }
4278
4279                 switch (level) {
4280                 case 0:
4281                         result = construct_printer_info0(info, session_info,
4282                                                          msg_ctx, info2,
4283                                                          servername,
4284                                                          &info[count].info0, snum);
4285                         break;
4286                 case 1:
4287                         result = construct_printer_info1(info, info2, flags,
4288                                                          servername,
4289                                                          &info[count].info1, snum);
4290                         break;
4291                 case 2:
4292                         result = construct_printer_info2(info, msg_ctx, info2,
4293                                                          servername,
4294                                                          &info[count].info2, snum);
4295                         break;
4296                 case 4:
4297                         result = construct_printer_info4(info, info2,
4298                                                          servername,
4299                                                          &info[count].info4, snum);
4300                         break;
4301                 case 5:
4302                         result = construct_printer_info5(info, info2,
4303                                                          servername,
4304                                                          &info[count].info5, snum);
4305                         break;
4306
4307                 default:
4308                         result = WERR_UNKNOWN_LEVEL;
4309                         goto out;
4310                 }
4311
4312                 if (!W_ERROR_IS_OK(result)) {
4313                         goto out;
4314                 }
4315
4316                 count++;
4317         }
4318
4319         *count_p = count;
4320         *info_p = info;
4321
4322  out:
4323         if (!W_ERROR_IS_OK(result)) {
4324                 TALLOC_FREE(info);
4325                 return result;
4326         }
4327
4328         *info_p = info;
4329
4330         return WERR_OK;
4331 }
4332
4333 /********************************************************************
4334  * handle enumeration of printers at level 0
4335  ********************************************************************/
4336
4337 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4338                                   const struct auth_serversupplied_info *session_info,
4339                                   struct messaging_context *msg_ctx,
4340                                   uint32_t flags,
4341                                   const char *servername,
4342                                   union spoolss_PrinterInfo **info,
4343                                   uint32_t *count)
4344 {
4345         DEBUG(4,("enum_all_printers_info_0\n"));
4346
4347         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4348                                             servername, 0, flags, info, count);
4349 }
4350
4351
4352 /********************************************************************
4353 ********************************************************************/
4354
4355 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4356                                        const struct auth_serversupplied_info *session_info,
4357                                        struct messaging_context *msg_ctx,
4358                                        const char *servername,
4359                                        uint32_t flags,
4360                                        union spoolss_PrinterInfo **info,
4361                                        uint32_t *count)
4362 {
4363         DEBUG(4,("enum_all_printers_info_1\n"));
4364
4365         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4366                                             servername, 1, flags, info, count);
4367 }
4368
4369 /********************************************************************
4370  enum_all_printers_info_1_local.
4371 *********************************************************************/
4372
4373 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4374                                              const struct auth_serversupplied_info *session_info,
4375                                              struct messaging_context *msg_ctx,
4376                                              const char *servername,
4377                                              union spoolss_PrinterInfo **info,
4378                                              uint32_t *count)
4379 {
4380         DEBUG(4,("enum_all_printers_info_1_local\n"));
4381
4382         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4383                                         servername, PRINTER_ENUM_ICON8, info, count);
4384 }
4385
4386 /********************************************************************
4387  enum_all_printers_info_1_name.
4388 *********************************************************************/
4389
4390 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4391                                             const struct auth_serversupplied_info *session_info,
4392                                             struct messaging_context *msg_ctx,
4393                                             const char *servername,
4394                                             union spoolss_PrinterInfo **info,
4395                                             uint32_t *count)
4396 {
4397         const char *s = servername;
4398
4399         DEBUG(4,("enum_all_printers_info_1_name\n"));
4400
4401         if ((servername[0] == '\\') && (servername[1] == '\\')) {
4402                 s = servername + 2;
4403         }
4404
4405         if (!is_myname_or_ipaddr(s)) {
4406                 return WERR_INVALID_NAME;
4407         }
4408
4409         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4410                                         servername, PRINTER_ENUM_ICON8, info, count);
4411 }
4412
4413 /********************************************************************
4414  enum_all_printers_info_1_network.
4415 *********************************************************************/
4416
4417 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4418                                                const struct auth_serversupplied_info *session_info,
4419                                                struct messaging_context *msg_ctx,
4420                                                const char *servername,
4421                                                union spoolss_PrinterInfo **info,
4422                                                uint32_t *count)
4423 {
4424         const char *s = servername;
4425
4426         DEBUG(4,("enum_all_printers_info_1_network\n"));
4427
4428         /* If we respond to a enum_printers level 1 on our name with flags
4429            set to PRINTER_ENUM_REMOTE with a list of printers then these
4430            printers incorrectly appear in the APW browse list.
4431            Specifically the printers for the server appear at the workgroup
4432            level where all the other servers in the domain are
4433            listed. Windows responds to this call with a
4434            WERR_CAN_NOT_COMPLETE so we should do the same. */
4435
4436         if (servername[0] == '\\' && servername[1] == '\\') {
4437                  s = servername + 2;
4438         }
4439
4440         if (is_myname_or_ipaddr(s)) {
4441                  return WERR_CAN_NOT_COMPLETE;
4442         }
4443
4444         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4445                                         servername, PRINTER_ENUM_NAME, info, count);
4446 }
4447
4448 /********************************************************************
4449  * api_spoolss_enumprinters
4450  *
4451  * called from api_spoolss_enumprinters (see this to understand)
4452  ********************************************************************/
4453
4454 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4455                                        const struct auth_serversupplied_info *session_info,
4456                                        struct messaging_context *msg_ctx,
4457                                        const char *servername,
4458                                        union spoolss_PrinterInfo **info,
4459                                        uint32_t *count)
4460 {
4461         DEBUG(4,("enum_all_printers_info_2\n"));
4462
4463         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4464                                             servername, 2, 0, info, count);
4465 }
4466
4467 /********************************************************************
4468  * handle enumeration of printers at level 1
4469  ********************************************************************/
4470
4471 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4472                                   const struct auth_serversupplied_info *session_info,
4473                                   struct messaging_context *msg_ctx,
4474                                   uint32_t flags,
4475                                   const char *servername,
4476                                   union spoolss_PrinterInfo **info,
4477                                   uint32_t *count)
4478 {
4479         /* Not all the flags are equals */
4480
4481         if (flags & PRINTER_ENUM_LOCAL) {
4482                 return enum_all_printers_info_1_local(mem_ctx, session_info,
4483                                                       msg_ctx, servername, info, count);
4484         }
4485
4486         if (flags & PRINTER_ENUM_NAME) {
4487                 return enum_all_printers_info_1_name(mem_ctx, session_info,
4488                                                      msg_ctx, servername, info,
4489                                                      count);
4490         }
4491
4492         if (flags & PRINTER_ENUM_NETWORK) {
4493                 return enum_all_printers_info_1_network(mem_ctx, session_info,
4494                                                         msg_ctx, servername, info,
4495                                                         count);
4496         }
4497
4498         return WERR_OK; /* NT4sp5 does that */
4499 }
4500
4501 /********************************************************************
4502  * handle enumeration of printers at level 2
4503  ********************************************************************/
4504
4505 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4506                                   const struct auth_serversupplied_info *session_info,
4507                                   struct messaging_context *msg_ctx,
4508                                   uint32_t flags,
4509                                   const char *servername,
4510                                   union spoolss_PrinterInfo **info,
4511                                   uint32_t *count)
4512 {
4513         if (flags & PRINTER_ENUM_LOCAL) {
4514
4515                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4516                                                 servername,
4517                                                 info, count);
4518         }
4519
4520         if (flags & PRINTER_ENUM_NAME) {
4521                 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4522                         return WERR_INVALID_NAME;
4523                 }
4524
4525                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4526                                                 servername,
4527                                                 info, count);
4528         }
4529
4530         if (flags & PRINTER_ENUM_REMOTE) {
4531                 return WERR_UNKNOWN_LEVEL;
4532         }
4533
4534         return WERR_OK;
4535 }
4536
4537 /********************************************************************
4538  * handle enumeration of printers at level 4
4539  ********************************************************************/
4540
4541 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4542                                   const struct auth_serversupplied_info *session_info,
4543                                   struct messaging_context *msg_ctx,
4544                                   uint32_t flags,
4545                                   const char *servername,
4546                                   union spoolss_PrinterInfo **info,
4547                                   uint32_t *count)
4548 {
4549         DEBUG(4,("enum_all_printers_info_4\n"));
4550
4551         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4552                                             servername, 4, flags, info, count);
4553 }
4554
4555
4556 /********************************************************************
4557  * handle enumeration of printers at level 5
4558  ********************************************************************/
4559
4560 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4561                                   const struct auth_serversupplied_info *session_info,
4562                                   struct messaging_context *msg_ctx,
4563                                   uint32_t flags,
4564                                   const char *servername,
4565                                   union spoolss_PrinterInfo **info,
4566                                   uint32_t *count)
4567 {
4568         DEBUG(4,("enum_all_printers_info_5\n"));
4569
4570         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4571                                             servername, 5, flags, info, count);
4572 }
4573
4574 /****************************************************************
4575  _spoolss_EnumPrinters
4576 ****************************************************************/
4577
4578 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4579                              struct spoolss_EnumPrinters *r)
4580 {
4581         const struct auth_serversupplied_info *session_info = get_session_info_system();
4582         WERROR result;
4583
4584         /* that's an [in out] buffer */
4585
4586         if (!r->in.buffer && (r->in.offered != 0)) {
4587                 return WERR_INVALID_PARAM;
4588         }
4589
4590         DEBUG(4,("_spoolss_EnumPrinters\n"));
4591
4592         *r->out.needed = 0;
4593         *r->out.count = 0;
4594         *r->out.info = NULL;
4595
4596         /*
4597          * Level 1:
4598          *          flags==PRINTER_ENUM_NAME
4599          *           if name=="" then enumerates all printers
4600          *           if name!="" then enumerate the printer
4601          *          flags==PRINTER_ENUM_REMOTE
4602          *          name is NULL, enumerate printers
4603          * Level 2: name!="" enumerates printers, name can't be NULL
4604          * Level 3: doesn't exist
4605          * Level 4: does a local registry lookup
4606          * Level 5: same as Level 2
4607          */
4608
4609         if (r->in.server && r->in.server[0] == '\0') {
4610                 r->in.server = NULL;
4611         }
4612
4613         switch (r->in.level) {
4614         case 0:
4615                 result = enumprinters_level0(p->mem_ctx, session_info,
4616                                              p->msg_ctx, r->in.flags,
4617                                              r->in.server,
4618                                              r->out.info, r->out.count);
4619                 break;
4620         case 1:
4621                 result = enumprinters_level1(p->mem_ctx, session_info,
4622                                              p->msg_ctx, r->in.flags,
4623                                              r->in.server,
4624                                              r->out.info, r->out.count);
4625                 break;
4626         case 2:
4627                 result = enumprinters_level2(p->mem_ctx, session_info,
4628                                              p->msg_ctx, r->in.flags,
4629                                              r->in.server,
4630                                              r->out.info, r->out.count);
4631                 break;
4632         case 4:
4633                 result = enumprinters_level4(p->mem_ctx, session_info,
4634                                              p->msg_ctx, r->in.flags,
4635                                              r->in.server,
4636                                              r->out.info, r->out.count);
4637                 break;
4638         case 5:
4639                 result = enumprinters_level5(p->mem_ctx, session_info,
4640                                              p->msg_ctx, r->in.flags,
4641                                              r->in.server,
4642                                              r->out.info, r->out.count);
4643                 break;
4644         default:
4645                 return WERR_UNKNOWN_LEVEL;
4646         }
4647
4648         if (!W_ERROR_IS_OK(result)) {
4649                 return result;
4650         }
4651
4652         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4653                                                      spoolss_EnumPrinters,
4654                                                      *r->out.info, r->in.level,
4655                                                      *r->out.count);
4656         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4657         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4658
4659         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4660 }
4661
4662 /****************************************************************
4663  _spoolss_GetPrinter
4664 ****************************************************************/
4665
4666 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4667                            struct spoolss_GetPrinter *r)
4668 {
4669         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4670         struct spoolss_PrinterInfo2 *info2 = NULL;
4671         WERROR result = WERR_OK;
4672         int snum;
4673
4674         /* that's an [in out] buffer */
4675
4676         if (!r->in.buffer && (r->in.offered != 0)) {
4677                 return WERR_INVALID_PARAM;
4678         }
4679
4680         *r->out.needed = 0;
4681
4682         if (Printer == NULL) {
4683                 return WERR_BADFID;
4684         }
4685
4686         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4687                 return WERR_BADFID;
4688         }
4689
4690         result = winreg_get_printer(p->mem_ctx,
4691                                     get_session_info_system(),
4692                                     p->msg_ctx,
4693                                     lp_const_servicename(snum),
4694                                     &info2);
4695         if (!W_ERROR_IS_OK(result)) {
4696                 goto out;
4697         }
4698
4699         switch (r->in.level) {
4700         case 0:
4701                 result = construct_printer_info0(p->mem_ctx,
4702                                                  get_session_info_system(),
4703                                                  p->msg_ctx,
4704                                                  info2,
4705                                                  Printer->servername,
4706                                                  &r->out.info->info0,
4707                                                  snum);
4708                 break;
4709         case 1:
4710                 result = construct_printer_info1(p->mem_ctx, info2,
4711                                                  PRINTER_ENUM_ICON8,
4712                                                  Printer->servername,
4713                                                  &r->out.info->info1, snum);
4714                 break;
4715         case 2:
4716                 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4717                                                  Printer->servername,
4718                                                  &r->out.info->info2, snum);
4719                 break;
4720         case 3:
4721                 result = construct_printer_info3(p->mem_ctx, info2,
4722                                                  Printer->servername,
4723                                                  &r->out.info->info3, snum);
4724                 break;
4725         case 4:
4726                 result = construct_printer_info4(p->mem_ctx, info2,
4727                                                  Printer->servername,
4728                                                  &r->out.info->info4, snum);
4729                 break;
4730         case 5:
4731                 result = construct_printer_info5(p->mem_ctx, info2,
4732                                                  Printer->servername,
4733                                                  &r->out.info->info5, snum);
4734                 break;
4735         case 6:
4736                 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4737                                                  Printer->servername,
4738                                                  &r->out.info->info6, snum);
4739                 break;
4740         case 7:
4741                 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4742                                                  Printer->servername,
4743                                                  &r->out.info->info7, snum);
4744                 break;
4745         case 8:
4746                 result = construct_printer_info8(p->mem_ctx, info2,
4747                                                  Printer->servername,
4748                                                  &r->out.info->info8, snum);
4749                 break;
4750         default:
4751                 result = WERR_UNKNOWN_LEVEL;
4752                 break;
4753         }
4754
4755  out:
4756         if (!W_ERROR_IS_OK(result)) {
4757                 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4758                           r->in.level, win_errstr(result)));
4759                 TALLOC_FREE(r->out.info);
4760                 return result;
4761         }
4762
4763         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4764                                                r->out.info, r->in.level);
4765         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4766
4767         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4768 }
4769
4770 /********************************************************************
4771  ********************************************************************/
4772
4773 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4774         do { \
4775                 if (in && strlen(in)) { \
4776                         out = talloc_strdup(mem_ctx, in); \
4777                 } else { \
4778                         out = talloc_strdup(mem_ctx, ""); \
4779                 } \
4780                 W_ERROR_HAVE_NO_MEMORY(out); \
4781         } while (0);
4782
4783 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4784         do { \
4785                 if (in && strlen(in)) { \
4786                         out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4787                 } else { \
4788                         out = talloc_strdup(mem_ctx, ""); \
4789                 } \
4790                 W_ERROR_HAVE_NO_MEMORY(out); \
4791         } while (0);
4792
4793 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4794                                                   const char **string_array,
4795                                                   const char ***presult,
4796                                                   const char *cservername,
4797                                                   const char *arch,
4798                                                   int version)
4799 {
4800         int i, num_strings = 0;
4801         const char **array = NULL;
4802
4803         if (string_array == NULL) {
4804                 return WERR_INVALID_PARAMETER;
4805         }
4806
4807         for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4808                 const char *str = NULL;
4809
4810                 if (cservername == NULL || arch == NULL) {
4811                         FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4812                 } else {
4813                         FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4814                 }
4815
4816                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4817                         TALLOC_FREE(array);
4818                         return WERR_NOMEM;
4819                 }
4820         }
4821
4822         if (i > 0) {
4823                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4824                              &array, &num_strings);
4825         }
4826
4827         if (presult) {
4828                 *presult = array;
4829         }
4830
4831         return WERR_OK;
4832 }
4833
4834 /********************************************************************
4835  * fill a spoolss_DriverInfo1 struct
4836  ********************************************************************/
4837
4838 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4839                                         struct spoolss_DriverInfo1 *r,
4840                                         const struct spoolss_DriverInfo8 *driver,
4841                                         const char *servername)
4842 {
4843         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4844         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4845
4846         return WERR_OK;
4847 }
4848
4849 /********************************************************************
4850  * fill a spoolss_DriverInfo2 struct
4851  ********************************************************************/
4852
4853 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4854                                         struct spoolss_DriverInfo2 *r,
4855                                         const struct spoolss_DriverInfo8 *driver,
4856                                         const char *servername)
4857
4858 {
4859         const char *cservername = canon_servername(servername);
4860
4861         r->version              = driver->version;
4862
4863         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4864         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4865         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4866         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4867
4868         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4869                                driver->architecture,
4870                                driver->version,
4871                                driver->driver_path,
4872                                r->driver_path);
4873
4874         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4875                                driver->architecture,
4876                                driver->version,
4877                                driver->data_file,
4878                                r->data_file);
4879
4880         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4881                                driver->architecture,
4882                                driver->version,
4883                                driver->config_file,
4884                                r->config_file);
4885
4886         return WERR_OK;
4887 }
4888
4889 /********************************************************************
4890  * fill a spoolss_DriverInfo3 struct
4891  ********************************************************************/
4892
4893 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4894                                         struct spoolss_DriverInfo3 *r,
4895                                         const struct spoolss_DriverInfo8 *driver,
4896                                         const char *servername)
4897 {
4898         const char *cservername = canon_servername(servername);
4899
4900         r->version              = driver->version;
4901
4902         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4903         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4904         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4905         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4906
4907         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4908                                driver->architecture,
4909                                driver->version,
4910                                driver->driver_path,
4911                                r->driver_path);
4912
4913         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4914                                driver->architecture,
4915                                driver->version,
4916                                driver->data_file,
4917                                r->data_file);
4918
4919         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4920                                driver->architecture,
4921                                driver->version,
4922                                driver->config_file,
4923                                r->config_file);
4924
4925         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4926                                driver->architecture,
4927                                driver->version,
4928                                driver->help_file,
4929                                r->help_file);
4930
4931         FILL_DRIVER_STRING(mem_ctx,
4932                            driver->monitor_name,
4933                            r->monitor_name);
4934
4935         FILL_DRIVER_STRING(mem_ctx,
4936                            driver->default_datatype,
4937                            r->default_datatype);
4938
4939         return string_array_from_driver_info(mem_ctx,
4940                                              driver->dependent_files,
4941                                              &r->dependent_files,
4942                                              cservername,
4943                                              driver->architecture,
4944                                              driver->version);
4945 }
4946
4947 /********************************************************************
4948  * fill a spoolss_DriverInfo4 struct
4949  ********************************************************************/
4950
4951 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4952                                         struct spoolss_DriverInfo4 *r,
4953                                         const struct spoolss_DriverInfo8 *driver,
4954                                         const char *servername)
4955 {
4956         const char *cservername = canon_servername(servername);
4957         WERROR result;
4958
4959         r->version              = driver->version;
4960
4961         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4962         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4963         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4964         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4965
4966         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4967                                driver->architecture,
4968                                driver->version,
4969                                driver->driver_path,
4970                                r->driver_path);
4971
4972         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4973                                driver->architecture,
4974                                driver->version,
4975                                driver->data_file,
4976                                r->data_file);
4977
4978         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4979                                driver->architecture,
4980                                driver->version,
4981                                driver->config_file,
4982                                r->config_file);
4983
4984         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4985                                driver->architecture,
4986                                driver->version,
4987                                driver->help_file,
4988                                r->help_file);
4989
4990         result = string_array_from_driver_info(mem_ctx,
4991                                                driver->dependent_files,
4992                                                &r->dependent_files,
4993                                                cservername,
4994                                                driver->architecture,
4995                                                driver->version);
4996         if (!W_ERROR_IS_OK(result)) {
4997                 return result;
4998         }
4999
5000         FILL_DRIVER_STRING(mem_ctx,
5001                            driver->monitor_name,
5002                            r->monitor_name);
5003
5004         FILL_DRIVER_STRING(mem_ctx,
5005                            driver->default_datatype,
5006                            r->default_datatype);
5007
5008
5009         result = string_array_from_driver_info(mem_ctx,
5010                                                driver->previous_names,
5011                                                &r->previous_names,
5012                                                NULL, NULL, 0);
5013
5014         return result;
5015 }
5016
5017 /********************************************************************
5018  * fill a spoolss_DriverInfo5 struct
5019  ********************************************************************/
5020
5021 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5022                                         struct spoolss_DriverInfo5 *r,
5023                                         const struct spoolss_DriverInfo8 *driver,
5024                                         const char *servername)
5025 {
5026         const char *cservername = canon_servername(servername);
5027
5028         r->version              = driver->version;
5029
5030         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5031         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5032         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5033         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5034
5035         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5036                                driver->architecture,
5037                                driver->version,
5038                                driver->driver_path,
5039                                r->driver_path);
5040
5041         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5042                                driver->architecture,
5043                                driver->version,
5044                                driver->data_file,
5045                                r->data_file);
5046
5047         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5048                                driver->architecture,
5049                                driver->version,
5050                                driver->config_file,
5051                                r->config_file);
5052
5053         r->driver_attributes    = 0;
5054         r->config_version       = 0;
5055         r->driver_version       = 0;
5056
5057         return WERR_OK;
5058 }
5059 /********************************************************************
5060  * fill a spoolss_DriverInfo6 struct
5061  ********************************************************************/
5062
5063 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5064                                         struct spoolss_DriverInfo6 *r,
5065                                         const struct spoolss_DriverInfo8 *driver,
5066                                         const char *servername)
5067 {
5068         const char *cservername = canon_servername(servername);
5069         WERROR result;
5070
5071         r->version              = driver->version;
5072
5073         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5074         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5075         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5076         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5077
5078         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5079                                driver->architecture,
5080                                driver->version,
5081                                driver->driver_path,
5082                                r->driver_path);
5083
5084         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5085                                driver->architecture,
5086                                driver->version,
5087                                driver->data_file,
5088                                r->data_file);
5089
5090         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5091                                driver->architecture,
5092                                driver->version,
5093                                driver->config_file,
5094                                r->config_file);
5095
5096         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5097                                driver->architecture,
5098                                driver->version,
5099                                driver->help_file,
5100                                r->help_file);
5101
5102         FILL_DRIVER_STRING(mem_ctx,
5103                            driver->monitor_name,
5104                            r->monitor_name);
5105
5106         FILL_DRIVER_STRING(mem_ctx,
5107                            driver->default_datatype,
5108                            r->default_datatype);
5109
5110         result = string_array_from_driver_info(mem_ctx,
5111                                                driver->dependent_files,
5112                                                &r->dependent_files,
5113                                                cservername,
5114                                                driver->architecture,
5115                                                driver->version);
5116         if (!W_ERROR_IS_OK(result)) {
5117                 return result;
5118         }
5119
5120         result = string_array_from_driver_info(mem_ctx,
5121                                                driver->previous_names,
5122                                                &r->previous_names,
5123                                                NULL, NULL, 0);
5124         if (!W_ERROR_IS_OK(result)) {
5125                 return result;
5126         }
5127
5128         r->driver_date          = driver->driver_date;
5129         r->driver_version       = driver->driver_version;
5130
5131         FILL_DRIVER_STRING(mem_ctx,
5132                            driver->manufacturer_name,
5133                            r->manufacturer_name);
5134         FILL_DRIVER_STRING(mem_ctx,
5135                            driver->manufacturer_url,
5136                            r->manufacturer_url);
5137         FILL_DRIVER_STRING(mem_ctx,
5138                            driver->hardware_id,
5139                            r->hardware_id);
5140         FILL_DRIVER_STRING(mem_ctx,
5141                            driver->provider,
5142                            r->provider);
5143
5144         return WERR_OK;
5145 }
5146
5147 /********************************************************************
5148  * fill a spoolss_DriverInfo8 struct
5149  ********************************************************************/
5150
5151 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5152                                         struct spoolss_DriverInfo8 *r,
5153                                         const struct spoolss_DriverInfo8 *driver,
5154                                         const char *servername)
5155 {
5156         const char *cservername = canon_servername(servername);
5157         WERROR result;
5158
5159         r->version              = driver->version;
5160
5161         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5162         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5163         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5164         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5165
5166         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5167                                driver->architecture,
5168                                driver->version,
5169                                driver->driver_path,
5170                                r->driver_path);
5171
5172         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5173                                driver->architecture,
5174                                driver->version,
5175                                driver->data_file,
5176                                r->data_file);
5177
5178         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5179                                driver->architecture,
5180                                driver->version,
5181                                driver->config_file,
5182                                r->config_file);
5183
5184         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5185                                driver->architecture,
5186                                driver->version,
5187                                driver->help_file,
5188                                r->help_file);
5189
5190         FILL_DRIVER_STRING(mem_ctx,
5191                            driver->monitor_name,
5192                            r->monitor_name);
5193
5194         FILL_DRIVER_STRING(mem_ctx,
5195                            driver->default_datatype,
5196                            r->default_datatype);
5197
5198         result = string_array_from_driver_info(mem_ctx,
5199                                                driver->dependent_files,
5200                                                &r->dependent_files,
5201                                                cservername,
5202                                                driver->architecture,
5203                                                driver->version);
5204         if (!W_ERROR_IS_OK(result)) {
5205                 return result;
5206         }
5207
5208         result = string_array_from_driver_info(mem_ctx,
5209                                                driver->previous_names,
5210                                                &r->previous_names,
5211                                                NULL, NULL, 0);
5212         if (!W_ERROR_IS_OK(result)) {
5213                 return result;
5214         }
5215
5216         r->driver_date          = driver->driver_date;
5217         r->driver_version       = driver->driver_version;
5218
5219         FILL_DRIVER_STRING(mem_ctx,
5220                            driver->manufacturer_name,
5221                            r->manufacturer_name);
5222         FILL_DRIVER_STRING(mem_ctx,
5223                            driver->manufacturer_url,
5224                            r->manufacturer_url);
5225         FILL_DRIVER_STRING(mem_ctx,
5226                            driver->hardware_id,
5227                            r->hardware_id);
5228         FILL_DRIVER_STRING(mem_ctx,
5229                            driver->provider,
5230                            r->provider);
5231
5232         FILL_DRIVER_STRING(mem_ctx,
5233                            driver->print_processor,
5234                            r->print_processor);
5235         FILL_DRIVER_STRING(mem_ctx,
5236                            driver->vendor_setup,
5237                            r->vendor_setup);
5238
5239         result = string_array_from_driver_info(mem_ctx,
5240                                                driver->color_profiles,
5241                                                &r->color_profiles,
5242                                                NULL, NULL, 0);
5243         if (!W_ERROR_IS_OK(result)) {
5244                 return result;
5245         }
5246
5247         FILL_DRIVER_STRING(mem_ctx,
5248                            driver->inf_path,
5249                            r->inf_path);
5250
5251         r->printer_driver_attributes    = driver->printer_driver_attributes;
5252
5253         result = string_array_from_driver_info(mem_ctx,
5254                                                driver->core_driver_dependencies,
5255                                                &r->core_driver_dependencies,
5256                                                NULL, NULL, 0);
5257         if (!W_ERROR_IS_OK(result)) {
5258                 return result;
5259         }
5260
5261         r->min_inbox_driver_ver_date    = driver->min_inbox_driver_ver_date;
5262         r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5263
5264         return WERR_OK;
5265 }
5266
5267 #if 0 /* disabled until marshalling issues are resolved - gd */
5268 /********************************************************************
5269  ********************************************************************/
5270
5271 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5272                                           struct spoolss_DriverFileInfo *r,
5273                                           const char *cservername,
5274                                           const char *file_name,
5275                                           enum spoolss_DriverFileType file_type,
5276                                           uint32_t file_version)
5277 {
5278         r->file_name    = talloc_asprintf(mem_ctx, "\\\\%s%s",
5279                                           cservername, file_name);
5280         W_ERROR_HAVE_NO_MEMORY(r->file_name);
5281         r->file_type    = file_type;
5282         r->file_version = file_version;
5283
5284         return WERR_OK;
5285 }
5286
5287 /********************************************************************
5288  ********************************************************************/
5289
5290 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5291                                                  const struct spoolss_DriverInfo8 *driver,
5292                                                  const char *cservername,
5293                                                  struct spoolss_DriverFileInfo **info_p,
5294                                                  uint32_t *count_p)
5295 {
5296         struct spoolss_DriverFileInfo *info = NULL;
5297         uint32_t count = 0;
5298         WERROR result;
5299         uint32_t i;
5300
5301         *info_p = NULL;
5302         *count_p = 0;
5303
5304         if (strlen(driver->driver_path)) {
5305                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5306                                             struct spoolss_DriverFileInfo,
5307                                             count + 1);
5308                 W_ERROR_HAVE_NO_MEMORY(info);
5309                 result = fill_spoolss_DriverFileInfo(info,
5310                                                      &info[count],
5311                                                      cservername,
5312                                                      driver->driver_path,
5313                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5314                                                      0);
5315                 W_ERROR_NOT_OK_RETURN(result);
5316                 count++;
5317         }
5318
5319         if (strlen(driver->config_file)) {
5320                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5321                                             struct spoolss_DriverFileInfo,
5322                                             count + 1);
5323                 W_ERROR_HAVE_NO_MEMORY(info);
5324                 result = fill_spoolss_DriverFileInfo(info,
5325                                                      &info[count],
5326                                                      cservername,
5327                                                      driver->config_file,
5328                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5329                                                      0);
5330                 W_ERROR_NOT_OK_RETURN(result);
5331                 count++;
5332         }
5333
5334         if (strlen(driver->data_file)) {
5335                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5336                                             struct spoolss_DriverFileInfo,
5337                                             count + 1);
5338                 W_ERROR_HAVE_NO_MEMORY(info);
5339                 result = fill_spoolss_DriverFileInfo(info,
5340                                                      &info[count],
5341                                                      cservername,
5342                                                      driver->data_file,
5343                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
5344                                                      0);
5345                 W_ERROR_NOT_OK_RETURN(result);
5346                 count++;
5347         }
5348
5349         if (strlen(driver->help_file)) {
5350                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5351                                             struct spoolss_DriverFileInfo,
5352                                             count + 1);
5353                 W_ERROR_HAVE_NO_MEMORY(info);
5354                 result = fill_spoolss_DriverFileInfo(info,
5355                                                      &info[count],
5356                                                      cservername,
5357                                                      driver->help_file,
5358                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
5359                                                      0);
5360                 W_ERROR_NOT_OK_RETURN(result);
5361                 count++;
5362         }
5363
5364         for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5365                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5366                                             struct spoolss_DriverFileInfo,
5367                                             count + 1);
5368                 W_ERROR_HAVE_NO_MEMORY(info);
5369                 result = fill_spoolss_DriverFileInfo(info,
5370                                                      &info[count],
5371                                                      cservername,
5372                                                      driver->dependent_files[i],
5373                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5374                                                      0);
5375                 W_ERROR_NOT_OK_RETURN(result);
5376                 count++;
5377         }
5378
5379         *info_p = info;
5380         *count_p = count;
5381
5382         return WERR_OK;
5383 }
5384
5385 /********************************************************************
5386  * fill a spoolss_DriverInfo101 struct
5387  ********************************************************************/
5388
5389 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5390                                           struct spoolss_DriverInfo101 *r,
5391                                           const struct spoolss_DriverInfo8 *driver,
5392                                           const char *servername)
5393 {
5394         const char *cservername = canon_servername(servername);
5395         WERROR result;
5396
5397         r->version              = driver->version;
5398
5399         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5400         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5401         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5402         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5403
5404         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5405                                                     cservername,
5406                                                     &r->file_info,
5407                                                     &r->file_count);
5408         if (!W_ERROR_IS_OK(result)) {
5409                 return result;
5410         }
5411
5412         FILL_DRIVER_STRING(mem_ctx,
5413                            driver->monitor_name,
5414                            r->monitor_name);
5415
5416         FILL_DRIVER_STRING(mem_ctx,
5417                            driver->default_datatype,
5418                            r->default_datatype);
5419
5420         result = string_array_from_driver_info(mem_ctx,
5421                                                driver->previous_names,
5422                                                &r->previous_names,
5423                                                NULL, NULL, 0);
5424         if (!W_ERROR_IS_OK(result)) {
5425                 return result;
5426         }
5427
5428         r->driver_date          = driver->driver_date;
5429         r->driver_version       = driver->driver_version;
5430
5431         FILL_DRIVER_STRING(mem_ctx,
5432                            driver->manufacturer_name,
5433                            r->manufacturer_name);
5434         FILL_DRIVER_STRING(mem_ctx,
5435                            driver->manufacturer_url,
5436                            r->manufacturer_url);
5437         FILL_DRIVER_STRING(mem_ctx,
5438                            driver->hardware_id,
5439                            r->hardware_id);
5440         FILL_DRIVER_STRING(mem_ctx,
5441                            driver->provider,
5442                            r->provider);
5443
5444         return WERR_OK;
5445 }
5446 #endif
5447 /********************************************************************
5448  ********************************************************************/
5449
5450 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5451                                                   const struct auth_serversupplied_info *session_info,
5452                                                   struct messaging_context *msg_ctx,
5453                                                   uint32_t level,
5454                                                   union spoolss_DriverInfo *r,
5455                                                   int snum,
5456                                                   const char *servername,
5457                                                   const char *architecture,
5458                                                   uint32_t version)
5459 {
5460         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5461         struct spoolss_DriverInfo8 *driver;
5462         WERROR result;
5463
5464         if (level == 101) {
5465                 return WERR_UNKNOWN_LEVEL;
5466         }
5467
5468         result = winreg_get_printer(mem_ctx,
5469                                     session_info,
5470                                     msg_ctx,
5471                                     lp_const_servicename(snum),
5472                                     &pinfo2);
5473
5474         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5475                 win_errstr(result)));
5476
5477         if (!W_ERROR_IS_OK(result)) {
5478                 return WERR_INVALID_PRINTER_NAME;
5479         }
5480
5481         result = winreg_get_driver(mem_ctx, session_info, msg_ctx,
5482                                    architecture,
5483                                    pinfo2->drivername, version, &driver);
5484
5485         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5486                 win_errstr(result)));
5487
5488         if (!W_ERROR_IS_OK(result)) {
5489                 /*
5490                  * Is this a W2k client ?
5491                  */
5492
5493                 if (version < 3) {
5494                         talloc_free(pinfo2);
5495                         return WERR_UNKNOWN_PRINTER_DRIVER;
5496                 }
5497
5498                 /* Yes - try again with a WinNT driver. */
5499                 version = 2;
5500                 result = winreg_get_driver(mem_ctx, session_info, msg_ctx,
5501                                            architecture,
5502                                            pinfo2->drivername,
5503                                            version, &driver);
5504                 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5505                         win_errstr(result)));
5506                 if (!W_ERROR_IS_OK(result)) {
5507                         talloc_free(pinfo2);
5508                         return WERR_UNKNOWN_PRINTER_DRIVER;
5509                 }
5510         }
5511
5512         switch (level) {
5513         case 1:
5514                 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5515                 break;
5516         case 2:
5517                 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5518                 break;
5519         case 3:
5520                 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5521                 break;
5522         case 4:
5523                 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5524                 break;
5525         case 5:
5526                 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5527                 break;
5528         case 6:
5529                 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5530                 break;
5531         case 8:
5532                 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5533                 break;
5534 #if 0 /* disabled until marshalling issues are resolved - gd */
5535         case 101:
5536                 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5537                 break;
5538 #endif
5539         default:
5540                 result = WERR_UNKNOWN_LEVEL;
5541                 break;
5542         }
5543
5544         talloc_free(pinfo2);
5545         talloc_free(driver);
5546
5547         return result;
5548 }
5549
5550 /****************************************************************
5551  _spoolss_GetPrinterDriver2
5552 ****************************************************************/
5553
5554 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5555                                   struct spoolss_GetPrinterDriver2 *r)
5556 {
5557         struct printer_handle *printer;
5558         WERROR result;
5559
5560         int snum;
5561
5562         /* that's an [in out] buffer */
5563
5564         if (!r->in.buffer && (r->in.offered != 0)) {
5565                 return WERR_INVALID_PARAM;
5566         }
5567
5568         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5569
5570         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5571                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5572                 return WERR_INVALID_PRINTER_NAME;
5573         }
5574
5575         *r->out.needed = 0;
5576         *r->out.server_major_version = 0;
5577         *r->out.server_minor_version = 0;
5578
5579         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5580                 return WERR_BADFID;
5581         }
5582
5583         result = construct_printer_driver_info_level(p->mem_ctx,
5584                                                      get_session_info_system(),
5585                                                      p->msg_ctx,
5586                                                      r->in.level, r->out.info,
5587                                                      snum, printer->servername,
5588                                                      r->in.architecture,
5589                                                      r->in.client_major_version);
5590         if (!W_ERROR_IS_OK(result)) {
5591                 TALLOC_FREE(r->out.info);
5592                 return result;
5593         }
5594
5595         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5596                                                r->out.info, r->in.level);
5597         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5598
5599         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5600 }
5601
5602
5603 /****************************************************************
5604  _spoolss_StartPagePrinter
5605 ****************************************************************/
5606
5607 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5608                                  struct spoolss_StartPagePrinter *r)
5609 {
5610         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5611
5612         if (!Printer) {
5613                 DEBUG(3,("_spoolss_StartPagePrinter: "
5614                         "Error in startpageprinter printer handle\n"));
5615                 return WERR_BADFID;
5616         }
5617
5618         Printer->page_started = true;
5619         return WERR_OK;
5620 }
5621
5622 /****************************************************************
5623  _spoolss_EndPagePrinter
5624 ****************************************************************/
5625
5626 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5627                                struct spoolss_EndPagePrinter *r)
5628 {
5629         int snum;
5630
5631         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5632
5633         if (!Printer) {
5634                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5635                         OUR_HANDLE(r->in.handle)));
5636                 return WERR_BADFID;
5637         }
5638
5639         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5640                 return WERR_BADFID;
5641
5642         Printer->page_started = false;
5643         print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5644
5645         return WERR_OK;
5646 }
5647
5648 /****************************************************************
5649  _spoolss_StartDocPrinter
5650 ****************************************************************/
5651
5652 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5653                                 struct spoolss_StartDocPrinter *r)
5654 {
5655         struct spoolss_DocumentInfo1 *info_1;
5656         int snum;
5657         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5658         WERROR werr;
5659
5660         if (!Printer) {
5661                 DEBUG(2,("_spoolss_StartDocPrinter: "
5662                         "Invalid handle (%s:%u:%u)\n",
5663                         OUR_HANDLE(r->in.handle)));
5664                 return WERR_BADFID;
5665         }
5666
5667         if (Printer->jobid) {
5668                 DEBUG(2, ("_spoolss_StartDocPrinter: "
5669                           "StartDocPrinter called twice! "
5670                           "(existing jobid = %d)\n", Printer->jobid));
5671                 return WERR_INVALID_HANDLE;
5672         }
5673
5674         if (r->in.level != 1) {
5675                 return WERR_UNKNOWN_LEVEL;
5676         }
5677
5678         info_1 = r->in.info.info1;
5679
5680         /*
5681          * a nice thing with NT is it doesn't listen to what you tell it.
5682          * when asked to send _only_ RAW datas, it tries to send datas
5683          * in EMF format.
5684          *
5685          * So I add checks like in NT Server ...
5686          */
5687
5688         if (info_1->datatype) {
5689                 if (strcmp(info_1->datatype, "RAW") != 0) {
5690                         *r->out.job_id = 0;
5691                         return WERR_INVALID_DATATYPE;
5692                 }
5693         }
5694
5695         /* get the share number of the printer */
5696         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5697                 return WERR_BADFID;
5698         }
5699
5700         werr = print_job_start(p->session_info,
5701                                p->msg_ctx,
5702                                p->client_id->name,
5703                                snum,
5704                                info_1->document_name,
5705                                info_1->output_file,
5706                                Printer->devmode,
5707                                &Printer->jobid);
5708
5709         /* An error occured in print_job_start() so return an appropriate
5710            NT error code. */
5711
5712         if (!W_ERROR_IS_OK(werr)) {
5713                 return werr;
5714         }
5715
5716         Printer->document_started = true;
5717         *r->out.job_id = Printer->jobid;
5718
5719         return WERR_OK;
5720 }
5721
5722 /****************************************************************
5723  _spoolss_EndDocPrinter
5724 ****************************************************************/
5725
5726 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5727                               struct spoolss_EndDocPrinter *r)
5728 {
5729         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5730         NTSTATUS status;
5731         int snum;
5732
5733         if (!Printer) {
5734                 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5735                         OUR_HANDLE(r->in.handle)));
5736                 return WERR_BADFID;
5737         }
5738
5739         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5740                 return WERR_BADFID;
5741         }
5742
5743         Printer->document_started = false;
5744         status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5745         if (!NT_STATUS_IS_OK(status)) {
5746                 DEBUG(2, ("_spoolss_EndDocPrinter: "
5747                           "print_job_end failed [%s]\n",
5748                           nt_errstr(status)));
5749         }
5750
5751         Printer->jobid = 0;
5752         return ntstatus_to_werror(status);
5753 }
5754
5755 /****************************************************************
5756  _spoolss_WritePrinter
5757 ****************************************************************/
5758
5759 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5760                              struct spoolss_WritePrinter *r)
5761 {
5762         ssize_t buffer_written;
5763         int snum;
5764         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5765
5766         if (!Printer) {
5767                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5768                         OUR_HANDLE(r->in.handle)));
5769                 *r->out.num_written = r->in._data_size;
5770                 return WERR_BADFID;
5771         }
5772
5773         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5774                 return WERR_BADFID;
5775
5776         /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5777         buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5778                                                    snum, Printer->jobid,
5779                                                    (const char *)r->in.data.data,
5780                                                    (size_t)r->in._data_size);
5781         if (buffer_written == (ssize_t)-1) {
5782                 *r->out.num_written = 0;
5783                 if (errno == ENOSPC)
5784                         return WERR_NO_SPOOL_SPACE;
5785                 else
5786                         return WERR_ACCESS_DENIED;
5787         }
5788
5789         *r->out.num_written = r->in._data_size;
5790
5791         return WERR_OK;
5792 }
5793
5794 /********************************************************************
5795  * api_spoolss_getprinter
5796  * called from the spoolss dispatcher
5797  *
5798  ********************************************************************/
5799
5800 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5801                               struct pipes_struct *p)
5802 {
5803         const struct auth_serversupplied_info *session_info = p->session_info;
5804         int snum;
5805         WERROR errcode = WERR_BADFUNC;
5806         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5807
5808         if (!Printer) {
5809                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5810                         OUR_HANDLE(handle)));
5811                 return WERR_BADFID;
5812         }
5813
5814         if (!get_printer_snum(p, handle, &snum, NULL))
5815                 return WERR_BADFID;
5816
5817         switch (command) {
5818         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5819                 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
5820                 break;
5821         case SPOOLSS_PRINTER_CONTROL_RESUME:
5822         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5823                 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
5824                 break;
5825         case SPOOLSS_PRINTER_CONTROL_PURGE:
5826                 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
5827                 break;
5828         default:
5829                 return WERR_UNKNOWN_LEVEL;
5830         }
5831
5832         return errcode;
5833 }
5834
5835
5836 /****************************************************************
5837  _spoolss_AbortPrinter
5838  * From MSDN: "Deletes printer's spool file if printer is configured
5839  * for spooling"
5840 ****************************************************************/
5841
5842 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
5843                              struct spoolss_AbortPrinter *r)
5844 {
5845         struct printer_handle   *Printer = find_printer_index_by_hnd(p, r->in.handle);
5846         int             snum;
5847         WERROR          errcode = WERR_OK;
5848
5849         if (!Printer) {
5850                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5851                         OUR_HANDLE(r->in.handle)));
5852                 return WERR_BADFID;
5853         }
5854
5855         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5856                 return WERR_BADFID;
5857
5858         if (!Printer->document_started) {
5859                 return WERR_SPL_NO_STARTDOC;
5860         }
5861
5862         errcode = print_job_delete(p->session_info,
5863                                    p->msg_ctx,
5864                                    snum,
5865                                    Printer->jobid);
5866
5867         return errcode;
5868 }
5869
5870 /********************************************************************
5871  * called by spoolss_api_setprinter
5872  * when updating a printer description
5873  ********************************************************************/
5874
5875 static WERROR update_printer_sec(struct policy_handle *handle,
5876                                  struct pipes_struct *p,
5877                                  struct sec_desc_buf *secdesc_ctr)
5878 {
5879         struct spoolss_security_descriptor *new_secdesc = NULL;
5880         struct spoolss_security_descriptor *old_secdesc = NULL;
5881         const char *printer;
5882         WERROR result;
5883         int snum;
5884
5885         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5886
5887         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5888                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5889                          OUR_HANDLE(handle)));
5890
5891                 result = WERR_BADFID;
5892                 goto done;
5893         }
5894
5895         if (secdesc_ctr == NULL) {
5896                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5897                 result = WERR_INVALID_PARAM;
5898                 goto done;
5899         }
5900         printer = lp_const_servicename(snum);
5901
5902         /* Check the user has permissions to change the security
5903            descriptor.  By experimentation with two NT machines, the user
5904            requires Full Access to the printer to change security
5905            information. */
5906
5907         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5908                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5909                 result = WERR_ACCESS_DENIED;
5910                 goto done;
5911         }
5912
5913         /* NT seems to like setting the security descriptor even though
5914            nothing may have actually changed. */
5915         result = winreg_get_printer_secdesc(p->mem_ctx,
5916                                             get_session_info_system(),
5917                                             p->msg_ctx,
5918                                             printer,
5919                                             &old_secdesc);
5920         if (!W_ERROR_IS_OK(result)) {
5921                 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc() failed\n"));
5922                 result = WERR_BADFID;
5923                 goto done;
5924         }
5925
5926         if (DEBUGLEVEL >= 10) {
5927                 struct security_acl *the_acl;
5928                 int i;
5929
5930                 the_acl = old_secdesc->dacl;
5931                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5932                            printer, the_acl->num_aces));
5933
5934                 for (i = 0; i < the_acl->num_aces; i++) {
5935                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5936                                            &the_acl->aces[i].trustee),
5937                                   the_acl->aces[i].access_mask));
5938                 }
5939
5940                 the_acl = secdesc_ctr->sd->dacl;
5941
5942                 if (the_acl) {
5943                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5944                                    printer, the_acl->num_aces));
5945
5946                         for (i = 0; i < the_acl->num_aces; i++) {
5947                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5948                                                    &the_acl->aces[i].trustee),
5949                                            the_acl->aces[i].access_mask));
5950                         }
5951                 } else {
5952                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5953                 }
5954         }
5955
5956         new_secdesc = sec_desc_merge(p->mem_ctx, secdesc_ctr->sd, old_secdesc);
5957         if (new_secdesc == NULL) {
5958                 result = WERR_NOMEM;
5959                 goto done;
5960         }
5961
5962         if (security_descriptor_equal(new_secdesc, old_secdesc)) {
5963                 result = WERR_OK;
5964                 goto done;
5965         }
5966
5967         result = winreg_set_printer_secdesc(p->mem_ctx,
5968                                             get_session_info_system(),
5969                                             p->msg_ctx,
5970                                             printer,
5971                                             new_secdesc);
5972
5973  done:
5974         return result;
5975 }
5976
5977 /********************************************************************
5978  Canonicalize printer info from a client
5979  ********************************************************************/
5980
5981 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
5982                              struct spoolss_SetPrinterInfo2 *info2,
5983                              int snum)
5984 {
5985         fstring printername;
5986         const char *p;
5987
5988         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5989                 "portname=%s drivername=%s comment=%s location=%s\n",
5990                 info2->servername, info2->printername, info2->sharename,
5991                 info2->portname, info2->drivername, info2->comment,
5992                 info2->location));
5993
5994         /* we force some elements to "correct" values */
5995         info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
5996         if (info2->servername == NULL) {
5997                 return false;
5998         }
5999         info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6000         if (info2->sharename == NULL) {
6001                 return false;
6002         }
6003
6004         /* check to see if we allow printername != sharename */
6005         if (lp_force_printername(snum)) {
6006                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6007                                         global_myname(), info2->sharename);
6008         } else {
6009                 /* make sure printername is in \\server\printername format */
6010                 fstrcpy(printername, info2->printername);
6011                 p = printername;
6012                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6013                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6014                                 p++;
6015                 }
6016
6017                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6018                                         global_myname(), p);
6019         }
6020         if (info2->printername == NULL) {
6021                 return false;
6022         }
6023
6024         info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6025         info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6026
6027         return true;
6028 }
6029
6030 /****************************************************************************
6031 ****************************************************************************/
6032
6033 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6034 {
6035         char *cmd = lp_addport_cmd();
6036         char *command = NULL;
6037         int ret;
6038         bool is_print_op = false;
6039
6040         if ( !*cmd ) {
6041                 return WERR_ACCESS_DENIED;
6042         }
6043
6044         command = talloc_asprintf(ctx,
6045                         "%s \"%s\" \"%s\"", cmd, portname, uri );
6046         if (!command) {
6047                 return WERR_NOMEM;
6048         }
6049
6050         if ( token )
6051                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6052
6053         DEBUG(10,("Running [%s]\n", command));
6054
6055         /********* BEGIN SePrintOperatorPrivilege **********/
6056
6057         if ( is_print_op )
6058                 become_root();
6059
6060         ret = smbrun(command, NULL);
6061
6062         if ( is_print_op )
6063                 unbecome_root();
6064
6065         /********* END SePrintOperatorPrivilege **********/
6066
6067         DEBUGADD(10,("returned [%d]\n", ret));
6068
6069         TALLOC_FREE(command);
6070
6071         if ( ret != 0 ) {
6072                 return WERR_ACCESS_DENIED;
6073         }
6074
6075         return WERR_OK;
6076 }
6077
6078 /****************************************************************************
6079 ****************************************************************************/
6080
6081 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6082                              struct spoolss_SetPrinterInfo2 *info2,
6083                              const char *remote_machine,
6084                              struct messaging_context *msg_ctx)
6085 {
6086         char *cmd = lp_addprinter_cmd();
6087         char **qlines;
6088         char *command = NULL;
6089         int numlines;
6090         int ret;
6091         int fd;
6092         bool is_print_op = false;
6093
6094         if (!remote_machine) {
6095                 return false;
6096         }
6097
6098         command = talloc_asprintf(ctx,
6099                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6100                         cmd, info2->printername, info2->sharename,
6101                         info2->portname, info2->drivername,
6102                         info2->location, info2->comment, remote_machine);
6103         if (!command) {
6104                 return false;
6105         }
6106
6107         if ( token )
6108                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6109
6110         DEBUG(10,("Running [%s]\n", command));
6111
6112         /********* BEGIN SePrintOperatorPrivilege **********/
6113
6114         if ( is_print_op )
6115                 become_root();
6116
6117         if ( (ret = smbrun(command, &fd)) == 0 ) {
6118                 /* Tell everyone we updated smb.conf. */
6119                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6120         }
6121
6122         if ( is_print_op )
6123                 unbecome_root();
6124
6125         /********* END SePrintOperatorPrivilege **********/
6126
6127         DEBUGADD(10,("returned [%d]\n", ret));
6128
6129         TALLOC_FREE(command);
6130
6131         if ( ret != 0 ) {
6132                 if (fd != -1)
6133                         close(fd);
6134                 return false;
6135         }
6136
6137         /* reload our services immediately */
6138         become_root();
6139         reload_services(msg_ctx, -1, false);
6140         unbecome_root();
6141
6142         numlines = 0;
6143         /* Get lines and convert them back to dos-codepage */
6144         qlines = fd_lines_load(fd, &numlines, 0, NULL);
6145         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6146         close(fd);
6147
6148         /* Set the portname to what the script says the portname should be. */
6149         /* but don't require anything to be return from the script exit a good error code */
6150
6151         if (numlines) {
6152                 /* Set the portname to what the script says the portname should be. */
6153                 info2->portname = talloc_strdup(ctx, qlines[0]);
6154                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6155         }
6156
6157         TALLOC_FREE(qlines);
6158         return true;
6159 }
6160
6161 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6162                                const struct auth_serversupplied_info *session_info,
6163                                struct messaging_context *msg_ctx,
6164                                int snum,
6165                                struct spoolss_SetPrinterInfo2 *printer,
6166                                struct spoolss_PrinterInfo2 *old_printer)
6167 {
6168         bool force_update = (old_printer == NULL);
6169         const char *dnsdomname;
6170         const char *longname;
6171         const char *uncname;
6172         const char *spooling;
6173         DATA_BLOB buffer;
6174         WERROR result = WERR_OK;
6175
6176         if (force_update || !strequal(printer->drivername, old_printer->drivername)) {
6177                 push_reg_sz(mem_ctx, &buffer, printer->drivername);
6178                 winreg_set_printer_dataex(mem_ctx,
6179                                           session_info,
6180                                           msg_ctx,
6181                                           printer->sharename,
6182                                           SPOOL_DSSPOOLER_KEY,
6183                                           SPOOL_REG_DRIVERNAME,
6184                                           REG_SZ,
6185                                           buffer.data,
6186                                           buffer.length);
6187
6188                 if (!force_update) {
6189                         DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6190                                 printer->drivername));
6191
6192                         notify_printer_driver(server_event_context(), msg_ctx,
6193                                               snum, printer->drivername ?
6194                                               printer->drivername : "");
6195                 }
6196         }
6197
6198         if (force_update || !strequal(printer->comment, old_printer->comment)) {
6199                 push_reg_sz(mem_ctx, &buffer, printer->comment);
6200                 winreg_set_printer_dataex(mem_ctx,
6201                                           session_info,
6202                                           msg_ctx,
6203                                           printer->sharename,
6204                                           SPOOL_DSSPOOLER_KEY,
6205                                           SPOOL_REG_DESCRIPTION,
6206                                           REG_SZ,
6207                                           buffer.data,
6208                                           buffer.length);
6209
6210                 if (!force_update) {
6211                         notify_printer_comment(server_event_context(), msg_ctx,
6212                                                snum, printer->comment ?
6213                                                printer->comment : "");
6214                 }
6215         }
6216
6217         if (force_update || !strequal(printer->sharename, old_printer->sharename)) {
6218                 push_reg_sz(mem_ctx, &buffer, printer->sharename);
6219                 winreg_set_printer_dataex(mem_ctx,
6220                                           session_info,
6221                                           msg_ctx,
6222                                           printer->sharename,
6223                                           SPOOL_DSSPOOLER_KEY,
6224                                           SPOOL_REG_PRINTSHARENAME,
6225                                           REG_SZ,
6226                                           buffer.data,
6227                                           buffer.length);
6228
6229                 if (!force_update) {
6230                         notify_printer_sharename(server_event_context(),
6231                                                  msg_ctx,
6232                                                  snum, printer->sharename ?
6233                                                  printer->sharename : "");
6234                 }
6235         }
6236
6237         if (force_update || !strequal(printer->printername, old_printer->printername)) {
6238                 const char *p;
6239
6240                 p = strrchr(printer->printername, '\\' );
6241                 if (p != NULL) {
6242                         p++;
6243                 } else {
6244                         p = printer->printername;
6245                 }
6246
6247                 push_reg_sz(mem_ctx, &buffer, p);
6248                 winreg_set_printer_dataex(mem_ctx,
6249                                           session_info,
6250                                           msg_ctx,
6251                                           printer->sharename,
6252                                           SPOOL_DSSPOOLER_KEY,
6253                                           SPOOL_REG_PRINTERNAME,
6254                                           REG_SZ,
6255                                           buffer.data,
6256                                           buffer.length);
6257
6258                 if (!force_update) {
6259                         notify_printer_printername(server_event_context(),
6260                                                    msg_ctx, snum, p ? p : "");
6261                 }
6262         }
6263
6264         if (force_update || !strequal(printer->portname, old_printer->portname)) {
6265                 push_reg_sz(mem_ctx, &buffer, printer->portname);
6266                 winreg_set_printer_dataex(mem_ctx,
6267                                           session_info,
6268                                           msg_ctx,
6269                                           printer->sharename,
6270                                           SPOOL_DSSPOOLER_KEY,
6271                                           SPOOL_REG_PORTNAME,
6272                                           REG_SZ,
6273                                           buffer.data,
6274                                           buffer.length);
6275
6276                 if (!force_update) {
6277                         notify_printer_port(server_event_context(),
6278                                             msg_ctx, snum, printer->portname ?
6279                                             printer->portname : "");
6280                 }
6281         }
6282
6283         if (force_update || !strequal(printer->location, old_printer->location)) {
6284                 push_reg_sz(mem_ctx, &buffer, printer->location);
6285                 winreg_set_printer_dataex(mem_ctx,
6286                                           session_info,
6287                                           msg_ctx,
6288                                           printer->sharename,
6289                                           SPOOL_DSSPOOLER_KEY,
6290                                           SPOOL_REG_LOCATION,
6291                                           REG_SZ,
6292                                           buffer.data,
6293                                           buffer.length);
6294
6295                 if (!force_update) {
6296                         notify_printer_location(server_event_context(),
6297                                                 msg_ctx, snum,
6298                                                 printer->location ?
6299                                                 printer->location : "");
6300                 }
6301         }
6302
6303         if (force_update || !strequal(printer->sepfile, old_printer->sepfile)) {
6304                 push_reg_sz(mem_ctx, &buffer, printer->sepfile);
6305                 winreg_set_printer_dataex(mem_ctx,
6306                                           session_info,
6307                                           msg_ctx,
6308                                           printer->sharename,
6309                                           SPOOL_DSSPOOLER_KEY,
6310                                           SPOOL_REG_PRINTSEPARATORFILE,
6311                                           REG_SZ,
6312                                           buffer.data,
6313                                           buffer.length);
6314
6315                 if (!force_update) {
6316                         notify_printer_sepfile(server_event_context(),
6317                                                msg_ctx, snum,
6318                                                printer->sepfile ?
6319                                                printer->sepfile : "");
6320                 }
6321         }
6322
6323         if (force_update || printer->starttime != old_printer->starttime) {
6324                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6325                 SIVAL(buffer.data, 0, printer->starttime);
6326                 winreg_set_printer_dataex(mem_ctx,
6327                                           session_info,
6328                                           msg_ctx,
6329                                           printer->sharename,
6330                                           SPOOL_DSSPOOLER_KEY,
6331                                           SPOOL_REG_PRINTSTARTTIME,
6332                                           REG_DWORD,
6333                                           buffer.data,
6334                                           buffer.length);
6335         }
6336
6337         if (force_update || printer->untiltime != old_printer->untiltime) {
6338                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6339                 SIVAL(buffer.data, 0, printer->untiltime);
6340                 winreg_set_printer_dataex(mem_ctx,
6341                                           session_info,
6342                                           msg_ctx,
6343                                           printer->sharename,
6344                                           SPOOL_DSSPOOLER_KEY,
6345                                           SPOOL_REG_PRINTENDTIME,
6346                                           REG_DWORD,
6347                                           buffer.data,
6348                                           buffer.length);
6349         }
6350
6351         if (force_update || printer->priority != old_printer->priority) {
6352                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6353                 SIVAL(buffer.data, 0, printer->priority);
6354                 winreg_set_printer_dataex(mem_ctx,
6355                                           session_info,
6356                                           msg_ctx,
6357                                           printer->sharename,
6358                                           SPOOL_DSSPOOLER_KEY,
6359                                           SPOOL_REG_PRIORITY,
6360                                           REG_DWORD,
6361                                           buffer.data,
6362                                           buffer.length);
6363         }
6364
6365         if (force_update || printer->attributes != old_printer->attributes) {
6366                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6367                 SIVAL(buffer.data, 0, (printer->attributes &
6368                                        PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6369                 winreg_set_printer_dataex(mem_ctx,
6370                                           session_info,
6371                                           msg_ctx,
6372                                           printer->sharename,
6373                                           SPOOL_DSSPOOLER_KEY,
6374                                           SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6375                                           REG_DWORD,
6376                                           buffer.data,
6377                                           buffer.length);
6378
6379                 switch (printer->attributes & 0x3) {
6380                         case 0:
6381                                 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6382                                 break;
6383                         case 1:
6384                                 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6385                                 break;
6386                         case 2:
6387                                 spooling = SPOOL_REGVAL_PRINTDIRECT;
6388                                 break;
6389                         default:
6390                                 spooling = "unknown";
6391                 }
6392                 push_reg_sz(mem_ctx, &buffer, spooling);
6393                 winreg_set_printer_dataex(mem_ctx,
6394                                           session_info,
6395                                           msg_ctx,
6396                                           printer->sharename,
6397                                           SPOOL_DSSPOOLER_KEY,
6398                                           SPOOL_REG_PRINTSPOOLING,
6399                                           REG_SZ,
6400                                           buffer.data,
6401                                           buffer.length);
6402         }
6403
6404         push_reg_sz(mem_ctx, &buffer, global_myname());
6405         winreg_set_printer_dataex(mem_ctx,
6406                                   session_info,
6407                                   msg_ctx,
6408                                   printer->sharename,
6409                                   SPOOL_DSSPOOLER_KEY,
6410                                   SPOOL_REG_SHORTSERVERNAME,
6411                                   REG_SZ,
6412                                   buffer.data,
6413                                   buffer.length);
6414
6415         dnsdomname = get_mydnsfullname();
6416         if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6417                 longname = talloc_strdup(mem_ctx, dnsdomname);
6418         } else {
6419                 longname = talloc_strdup(mem_ctx, global_myname());
6420         }
6421         if (longname == NULL) {
6422                 result = WERR_NOMEM;
6423                 goto done;
6424         }
6425
6426         push_reg_sz(mem_ctx, &buffer, longname);
6427         winreg_set_printer_dataex(mem_ctx,
6428                                   session_info,
6429                                   msg_ctx,
6430                                   printer->sharename,
6431                                   SPOOL_DSSPOOLER_KEY,
6432                                   SPOOL_REG_SERVERNAME,
6433                                   REG_SZ,
6434                                   buffer.data,
6435                                   buffer.length);
6436
6437         uncname = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6438                                   global_myname(), printer->sharename);
6439         push_reg_sz(mem_ctx, &buffer, uncname);
6440         winreg_set_printer_dataex(mem_ctx,
6441                                   session_info,
6442                                   msg_ctx,
6443                                   printer->sharename,
6444                                   SPOOL_DSSPOOLER_KEY,
6445                                   SPOOL_REG_UNCNAME,
6446                                   REG_SZ,
6447                                   buffer.data,
6448                                   buffer.length);
6449
6450 done:
6451         return result;
6452 }
6453
6454 /********************************************************************
6455  * Called by spoolss_api_setprinter
6456  * when updating a printer description.
6457  ********************************************************************/
6458
6459 static WERROR update_printer(struct pipes_struct *p,
6460                              struct policy_handle *handle,
6461                              struct spoolss_SetPrinterInfoCtr *info_ctr,
6462                              struct spoolss_DeviceMode *devmode)
6463 {
6464         uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6465         struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6466         struct spoolss_PrinterInfo2 *old_printer;
6467         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6468         int snum;
6469         WERROR result = WERR_OK;
6470         TALLOC_CTX *tmp_ctx;
6471
6472         DEBUG(8,("update_printer\n"));
6473
6474         tmp_ctx = talloc_new(p->mem_ctx);
6475         if (tmp_ctx == NULL) {
6476                 return WERR_NOMEM;
6477         }
6478
6479         if (!Printer) {
6480                 result = WERR_BADFID;
6481                 goto done;
6482         }
6483
6484         if (!get_printer_snum(p, handle, &snum, NULL)) {
6485                 result = WERR_BADFID;
6486                 goto done;
6487         }
6488
6489         result = winreg_get_printer(tmp_ctx,
6490                                     get_session_info_system(),
6491                                     p->msg_ctx,
6492                                     lp_const_servicename(snum),
6493                                     &old_printer);
6494         if (!W_ERROR_IS_OK(result)) {
6495                 result = WERR_BADFID;
6496                 goto done;
6497         }
6498
6499         /* Do sanity check on the requested changes for Samba */
6500         if (!check_printer_ok(tmp_ctx, printer, snum)) {
6501                 result = WERR_INVALID_PARAM;
6502                 goto done;
6503         }
6504
6505         /* FIXME!!! If the driver has changed we really should verify that
6506            it is installed before doing much else   --jerry */
6507
6508         /* Check calling user has permission to update printer description */
6509         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6510                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6511                 result = WERR_ACCESS_DENIED;
6512                 goto done;
6513         }
6514
6515         /* Call addprinter hook */
6516         /* Check changes to see if this is really needed */
6517
6518         if (*lp_addprinter_cmd() &&
6519                         (!strequal(printer->drivername, old_printer->drivername) ||
6520                          !strequal(printer->comment, old_printer->comment) ||
6521                          !strequal(printer->portname, old_printer->portname) ||
6522                          !strequal(printer->location, old_printer->location)) )
6523         {
6524                 /* add_printer_hook() will call reload_services() */
6525                 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6526                                       printer, p->client_id->addr,
6527                                       p->msg_ctx)) {
6528                         result = WERR_ACCESS_DENIED;
6529                         goto done;
6530                 }
6531         }
6532
6533         update_dsspooler(tmp_ctx,
6534                          get_session_info_system(),
6535                          p->msg_ctx,
6536                          snum,
6537                          printer,
6538                          old_printer);
6539
6540         printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6541
6542         if (devmode == NULL) {
6543                 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6544         }
6545         result = winreg_update_printer(tmp_ctx,
6546                                        get_session_info_system(),
6547                                        p->msg_ctx,
6548                                        printer->sharename,
6549                                        printer_mask,
6550                                        printer,
6551                                        devmode,
6552                                        NULL);
6553
6554 done:
6555         talloc_free(tmp_ctx);
6556
6557         return result;
6558 }
6559
6560 /****************************************************************************
6561 ****************************************************************************/
6562 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6563                                            struct policy_handle *handle,
6564                                            struct spoolss_SetPrinterInfo7 *info7)
6565 {
6566 #ifdef HAVE_ADS
6567         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6568         WERROR result;
6569         int snum;
6570         struct printer_handle *Printer;
6571
6572         if ( lp_security() != SEC_ADS ) {
6573                 return WERR_UNKNOWN_LEVEL;
6574         }
6575
6576         Printer = find_printer_index_by_hnd(p, handle);
6577
6578         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6579
6580         if (!Printer)
6581                 return WERR_BADFID;
6582
6583         if (!get_printer_snum(p, handle, &snum, NULL))
6584                 return WERR_BADFID;
6585
6586         result = winreg_get_printer(p->mem_ctx,
6587                                     get_session_info_system(),
6588                                     p->msg_ctx,
6589                                     lp_servicename(snum),
6590                                     &pinfo2);
6591         if (!W_ERROR_IS_OK(result)) {
6592                 return WERR_BADFID;
6593         }
6594
6595         nt_printer_publish(pinfo2,
6596                            get_session_info_system(),
6597                            p->msg_ctx,
6598                            pinfo2,
6599                            info7->action);
6600
6601         TALLOC_FREE(pinfo2);
6602         return WERR_OK;
6603 #else
6604         return WERR_UNKNOWN_LEVEL;
6605 #endif
6606 }
6607
6608 /********************************************************************
6609  ********************************************************************/
6610
6611 static WERROR update_printer_devmode(struct pipes_struct *p,
6612                                      struct policy_handle *handle,
6613                                      struct spoolss_DeviceMode *devmode)
6614 {
6615         int snum;
6616         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6617         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6618
6619         DEBUG(8,("update_printer_devmode\n"));
6620
6621         if (!Printer) {
6622                 return WERR_BADFID;
6623         }
6624
6625         if (!get_printer_snum(p, handle, &snum, NULL)) {
6626                 return WERR_BADFID;
6627         }
6628
6629         /* Check calling user has permission to update printer description */
6630         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6631                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6632                 return WERR_ACCESS_DENIED;
6633         }
6634
6635         return winreg_update_printer(p->mem_ctx,
6636                                      get_session_info_system(),
6637                                      p->msg_ctx,
6638                                      lp_const_servicename(snum),
6639                                      info2_mask,
6640                                      NULL,
6641                                      devmode,
6642                                      NULL);
6643 }
6644
6645
6646 /****************************************************************
6647  _spoolss_SetPrinter
6648 ****************************************************************/
6649
6650 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6651                            struct spoolss_SetPrinter *r)
6652 {
6653         WERROR result;
6654
6655         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6656
6657         if (!Printer) {
6658                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6659                         OUR_HANDLE(r->in.handle)));
6660                 return WERR_BADFID;
6661         }
6662
6663         /* check the level */
6664         switch (r->in.info_ctr->level) {
6665                 case 0:
6666                         return control_printer(r->in.handle, r->in.command, p);
6667                 case 2:
6668                         result = update_printer(p, r->in.handle,
6669                                                 r->in.info_ctr,
6670                                                 r->in.devmode_ctr->devmode);
6671                         if (!W_ERROR_IS_OK(result))
6672                                 return result;
6673                         if (r->in.secdesc_ctr->sd)
6674                                 result = update_printer_sec(r->in.handle, p,
6675                                                             r->in.secdesc_ctr);
6676                         return result;
6677                 case 3:
6678                         return update_printer_sec(r->in.handle, p,
6679                                                   r->in.secdesc_ctr);
6680                 case 7:
6681                         return publish_or_unpublish_printer(p, r->in.handle,
6682                                                             r->in.info_ctr->info.info7);
6683                 case 8:
6684                         return update_printer_devmode(p, r->in.handle,
6685                                                       r->in.devmode_ctr->devmode);
6686                 default:
6687                         return WERR_UNKNOWN_LEVEL;
6688         }
6689 }
6690
6691 /****************************************************************
6692  _spoolss_FindClosePrinterNotify
6693 ****************************************************************/
6694
6695 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
6696                                        struct spoolss_FindClosePrinterNotify *r)
6697 {
6698         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6699
6700         if (!Printer) {
6701                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6702                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6703                 return WERR_BADFID;
6704         }
6705
6706         if (Printer->notify.cli_chan != NULL &&
6707             Printer->notify.cli_chan->active_connections > 0) {
6708                 int snum = -1;
6709
6710                 if (Printer->printer_type == SPLHND_PRINTER) {
6711                         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6712                                 return WERR_BADFID;
6713                         }
6714                 }
6715
6716                 srv_spoolss_replycloseprinter(snum, Printer);
6717         }
6718
6719         Printer->notify.flags=0;
6720         Printer->notify.options=0;
6721         Printer->notify.localmachine[0]='\0';
6722         Printer->notify.printerlocal=0;
6723         TALLOC_FREE(Printer->notify.option);
6724
6725         return WERR_OK;
6726 }
6727
6728 /****************************************************************
6729  _spoolss_AddJob
6730 ****************************************************************/
6731
6732 WERROR _spoolss_AddJob(struct pipes_struct *p,
6733                        struct spoolss_AddJob *r)
6734 {
6735         if (!r->in.buffer && (r->in.offered != 0)) {
6736                 return WERR_INVALID_PARAM;
6737         }
6738
6739         /* this is what a NT server returns for AddJob. AddJob must fail on
6740          * non-local printers */
6741
6742         if (r->in.level != 1) {
6743                 return WERR_UNKNOWN_LEVEL;
6744         }
6745
6746         return WERR_INVALID_PARAM;
6747 }
6748
6749 /****************************************************************************
6750 fill_job_info1
6751 ****************************************************************************/
6752
6753 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6754                              struct spoolss_JobInfo1 *r,
6755                              const print_queue_struct *queue,
6756                              int position, int snum,
6757                              struct spoolss_PrinterInfo2 *pinfo2)
6758 {
6759         struct tm *t;
6760
6761         t = gmtime(&queue->time);
6762
6763         r->job_id               = queue->job;
6764
6765         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6766         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6767         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
6768         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6769         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6770         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6771         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6772         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6773         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6774         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6775         r->text_status          = talloc_strdup(mem_ctx, "");
6776         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6777
6778         r->status               = nt_printj_status(queue->status);
6779         r->priority             = queue->priority;
6780         r->position             = position;
6781         r->total_pages          = queue->page_count;
6782         r->pages_printed        = 0; /* ??? */
6783
6784         init_systemtime(&r->submitted, t);
6785
6786         return WERR_OK;
6787 }
6788
6789 /****************************************************************************
6790 fill_job_info2
6791 ****************************************************************************/
6792
6793 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6794                              struct spoolss_JobInfo2 *r,
6795                              const print_queue_struct *queue,
6796                              int position, int snum,
6797                              struct spoolss_PrinterInfo2 *pinfo2,
6798                              struct spoolss_DeviceMode *devmode)
6799 {
6800         struct tm *t;
6801
6802         t = gmtime(&queue->time);
6803
6804         r->job_id               = queue->job;
6805
6806         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6807         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6808         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
6809         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6810         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6811         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6812         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6813         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6814         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
6815         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6816         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6817         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6818         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
6819         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6820         r->parameters           = talloc_strdup(mem_ctx, "");
6821         W_ERROR_HAVE_NO_MEMORY(r->parameters);
6822         r->driver_name          = talloc_strdup(mem_ctx, pinfo2->drivername);
6823         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6824
6825         r->devmode              = devmode;
6826
6827         r->text_status          = talloc_strdup(mem_ctx, "");
6828         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6829
6830         r->secdesc              = NULL;
6831
6832         r->status               = nt_printj_status(queue->status);
6833         r->priority             = queue->priority;
6834         r->position             = position;
6835         r->start_time           = 0;
6836         r->until_time           = 0;
6837         r->total_pages          = queue->page_count;
6838         r->size                 = queue->size;
6839         init_systemtime(&r->submitted, t);
6840         r->time                 = 0;
6841         r->pages_printed        = 0; /* ??? */
6842
6843         return WERR_OK;
6844 }
6845
6846 /****************************************************************************
6847 fill_job_info3
6848 ****************************************************************************/
6849
6850 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6851                              struct spoolss_JobInfo3 *r,
6852                              const print_queue_struct *queue,
6853                              const print_queue_struct *next_queue,
6854                              int position, int snum,
6855                              struct spoolss_PrinterInfo2 *pinfo2)
6856 {
6857         r->job_id               = queue->job;
6858         r->next_job_id          = 0;
6859         if (next_queue) {
6860                 r->next_job_id  = next_queue->job;
6861         }
6862         r->reserved             = 0;
6863
6864         return WERR_OK;
6865 }
6866
6867 /****************************************************************************
6868  Enumjobs at level 1.
6869 ****************************************************************************/
6870
6871 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6872                               const print_queue_struct *queue,
6873                               uint32_t num_queues, int snum,
6874                               struct spoolss_PrinterInfo2 *pinfo2,
6875                               union spoolss_JobInfo **info_p,
6876                               uint32_t *count)
6877 {
6878         union spoolss_JobInfo *info;
6879         int i;
6880         WERROR result = WERR_OK;
6881
6882         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6883         W_ERROR_HAVE_NO_MEMORY(info);
6884
6885         *count = num_queues;
6886
6887         for (i=0; i<*count; i++) {
6888                 result = fill_job_info1(info,
6889                                         &info[i].info1,
6890                                         &queue[i],
6891                                         i,
6892                                         snum,
6893                                         pinfo2);
6894                 if (!W_ERROR_IS_OK(result)) {
6895                         goto out;
6896                 }
6897         }
6898
6899  out:
6900         if (!W_ERROR_IS_OK(result)) {
6901                 TALLOC_FREE(info);
6902                 *count = 0;
6903                 return result;
6904         }
6905
6906         *info_p = info;
6907
6908         return WERR_OK;
6909 }
6910
6911 /****************************************************************************
6912  Enumjobs at level 2.
6913 ****************************************************************************/
6914
6915 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6916                               const print_queue_struct *queue,
6917                               uint32_t num_queues, int snum,
6918                               struct spoolss_PrinterInfo2 *pinfo2,
6919                               union spoolss_JobInfo **info_p,
6920                               uint32_t *count)
6921 {
6922         union spoolss_JobInfo *info;
6923         int i;
6924         WERROR result = WERR_OK;
6925
6926         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6927         W_ERROR_HAVE_NO_MEMORY(info);
6928
6929         *count = num_queues;
6930
6931         for (i=0; i<*count; i++) {
6932                 struct spoolss_DeviceMode *devmode;
6933
6934                 result = spoolss_create_default_devmode(info,
6935                                                         pinfo2->printername,
6936                                                         &devmode);
6937                 if (!W_ERROR_IS_OK(result)) {
6938                         DEBUG(3, ("Can't proceed w/o a devmode!"));
6939                         goto out;
6940                 }
6941
6942                 result = fill_job_info2(info,
6943                                         &info[i].info2,
6944                                         &queue[i],
6945                                         i,
6946                                         snum,
6947                                         pinfo2,
6948                                         devmode);
6949                 if (!W_ERROR_IS_OK(result)) {
6950                         goto out;
6951                 }
6952         }
6953
6954  out:
6955         if (!W_ERROR_IS_OK(result)) {
6956                 TALLOC_FREE(info);
6957                 *count = 0;
6958                 return result;
6959         }
6960
6961         *info_p = info;
6962
6963         return WERR_OK;
6964 }
6965
6966 /****************************************************************************
6967  Enumjobs at level 3.
6968 ****************************************************************************/
6969
6970 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
6971                               const print_queue_struct *queue,
6972                               uint32_t num_queues, int snum,
6973                               struct spoolss_PrinterInfo2 *pinfo2,
6974                               union spoolss_JobInfo **info_p,
6975                               uint32_t *count)
6976 {
6977         union spoolss_JobInfo *info;
6978         int i;
6979         WERROR result = WERR_OK;
6980
6981         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6982         W_ERROR_HAVE_NO_MEMORY(info);
6983
6984         *count = num_queues;
6985
6986         for (i=0; i<*count; i++) {
6987                 const print_queue_struct *next_queue = NULL;
6988
6989                 if (i+1 < *count) {
6990                         next_queue = &queue[i+1];
6991                 }
6992
6993                 result = fill_job_info3(info,
6994                                         &info[i].info3,
6995                                         &queue[i],
6996                                         next_queue,
6997                                         i,
6998                                         snum,
6999                                         pinfo2);
7000                 if (!W_ERROR_IS_OK(result)) {
7001                         goto out;
7002                 }
7003         }
7004
7005  out:
7006         if (!W_ERROR_IS_OK(result)) {
7007                 TALLOC_FREE(info);
7008                 *count = 0;
7009                 return result;
7010         }
7011
7012         *info_p = info;
7013
7014         return WERR_OK;
7015 }
7016
7017 /****************************************************************
7018  _spoolss_EnumJobs
7019 ****************************************************************/
7020
7021 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7022                          struct spoolss_EnumJobs *r)
7023 {
7024         WERROR result;
7025         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7026         int snum;
7027         print_status_struct prt_status;
7028         print_queue_struct *queue = NULL;
7029         uint32_t count;
7030
7031         /* that's an [in out] buffer */
7032
7033         if (!r->in.buffer && (r->in.offered != 0)) {
7034                 return WERR_INVALID_PARAM;
7035         }
7036
7037         DEBUG(4,("_spoolss_EnumJobs\n"));
7038
7039         *r->out.needed = 0;
7040         *r->out.count = 0;
7041         *r->out.info = NULL;
7042
7043         /* lookup the printer snum and tdb entry */
7044
7045         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7046                 return WERR_BADFID;
7047         }
7048
7049         result = winreg_get_printer(p->mem_ctx,
7050                                     get_session_info_system(),
7051                                     p->msg_ctx,
7052                                     lp_const_servicename(snum),
7053                                     &pinfo2);
7054         if (!W_ERROR_IS_OK(result)) {
7055                 return result;
7056         }
7057
7058         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7059         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7060                 count, prt_status.status, prt_status.message));
7061
7062         if (count == 0) {
7063                 SAFE_FREE(queue);
7064                 TALLOC_FREE(pinfo2);
7065                 return WERR_OK;
7066         }
7067
7068         switch (r->in.level) {
7069         case 1:
7070                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7071                                          pinfo2, r->out.info, r->out.count);
7072                 break;
7073         case 2:
7074                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7075                                          pinfo2, r->out.info, r->out.count);
7076                 break;
7077         case 3:
7078                 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7079                                          pinfo2, r->out.info, r->out.count);
7080                 break;
7081         default:
7082                 result = WERR_UNKNOWN_LEVEL;
7083                 break;
7084         }
7085
7086         SAFE_FREE(queue);
7087         TALLOC_FREE(pinfo2);
7088
7089         if (!W_ERROR_IS_OK(result)) {
7090                 return result;
7091         }
7092
7093         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7094                                                      spoolss_EnumJobs,
7095                                                      *r->out.info, r->in.level,
7096                                                      *r->out.count);
7097         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7098         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7099
7100         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7101 }
7102
7103 /****************************************************************
7104  _spoolss_ScheduleJob
7105 ****************************************************************/
7106
7107 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7108                             struct spoolss_ScheduleJob *r)
7109 {
7110         return WERR_OK;
7111 }
7112
7113 /****************************************************************
7114 ****************************************************************/
7115
7116 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7117                                struct messaging_context *msg_ctx,
7118                                const char *printer_name,
7119                                uint32_t job_id,
7120                                struct spoolss_SetJobInfo1 *r)
7121 {
7122         char *old_doc_name;
7123
7124         if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7125                 return WERR_BADFID;
7126         }
7127
7128         if (strequal(old_doc_name, r->document_name)) {
7129                 return WERR_OK;
7130         }
7131
7132         if (!print_job_set_name(server_event_context(), msg_ctx,
7133                                 printer_name, job_id, r->document_name)) {
7134                 return WERR_BADFID;
7135         }
7136
7137         return WERR_OK;
7138 }
7139
7140 /****************************************************************
7141  _spoolss_SetJob
7142 ****************************************************************/
7143
7144 WERROR _spoolss_SetJob(struct pipes_struct *p,
7145                        struct spoolss_SetJob *r)
7146 {
7147         const struct auth_serversupplied_info *session_info = p->session_info;
7148         int snum;
7149         WERROR errcode = WERR_BADFUNC;
7150
7151         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7152                 return WERR_BADFID;
7153         }
7154
7155         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7156                 return WERR_INVALID_PRINTER_NAME;
7157         }
7158
7159         switch (r->in.command) {
7160         case SPOOLSS_JOB_CONTROL_CANCEL:
7161         case SPOOLSS_JOB_CONTROL_DELETE:
7162                 errcode = print_job_delete(session_info, p->msg_ctx,
7163                                            snum, r->in.job_id);
7164                 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7165                         errcode = WERR_OK;
7166                 }
7167                 break;
7168         case SPOOLSS_JOB_CONTROL_PAUSE:
7169                 if (print_job_pause(session_info, p->msg_ctx,
7170                                     snum, r->in.job_id, &errcode)) {
7171                         errcode = WERR_OK;
7172                 }
7173                 break;
7174         case SPOOLSS_JOB_CONTROL_RESTART:
7175         case SPOOLSS_JOB_CONTROL_RESUME:
7176                 if (print_job_resume(session_info, p->msg_ctx,
7177                                      snum, r->in.job_id, &errcode)) {
7178                         errcode = WERR_OK;
7179                 }
7180                 break;
7181         case 0:
7182                 errcode = WERR_OK;
7183                 break;
7184         default:
7185                 return WERR_UNKNOWN_LEVEL;
7186         }
7187
7188         if (!W_ERROR_IS_OK(errcode)) {
7189                 return errcode;
7190         }
7191
7192         if (r->in.ctr == NULL) {
7193                 return errcode;
7194         }
7195
7196         switch (r->in.ctr->level) {
7197         case 1:
7198                 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7199                                            lp_const_servicename(snum),
7200                                            r->in.job_id,
7201                                            r->in.ctr->info.info1);
7202                 break;
7203         case 2:
7204         case 3:
7205         case 4:
7206         default:
7207                 return WERR_UNKNOWN_LEVEL;
7208         }
7209
7210         return errcode;
7211 }
7212
7213 /****************************************************************************
7214  Enumerates all printer drivers by level and architecture.
7215 ****************************************************************************/
7216
7217 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7218                                                        const struct auth_serversupplied_info *session_info,
7219                                                        struct messaging_context *msg_ctx,
7220                                                        const char *servername,
7221                                                        const char *architecture,
7222                                                        uint32_t level,
7223                                                        union spoolss_DriverInfo **info_p,
7224                                                        uint32_t *count_p)
7225 {
7226         int i;
7227         uint32_t version;
7228         struct spoolss_DriverInfo8 *driver;
7229         union spoolss_DriverInfo *info = NULL;
7230         uint32_t count = 0;
7231         WERROR result = WERR_OK;
7232         uint32_t num_drivers;
7233         const char **drivers;
7234
7235         *count_p = 0;
7236         *info_p = NULL;
7237
7238         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7239                 result = winreg_get_driver_list(mem_ctx, session_info, msg_ctx,
7240                                                 architecture, version,
7241                                                 &num_drivers, &drivers);
7242                 if (!W_ERROR_IS_OK(result)) {
7243                         goto out;
7244                 }
7245                 DEBUG(4, ("we have:[%d] drivers in environment"
7246                           " [%s] and version [%d]\n",
7247                           num_drivers, architecture, version));
7248
7249                 if (num_drivers != 0) {
7250                         info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
7251                                                     union spoolss_DriverInfo,
7252                                                     count + num_drivers);
7253                         if (!info) {
7254                                 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7255                                         "failed to enlarge driver info buffer!\n"));
7256                                 result = WERR_NOMEM;
7257                                 goto out;
7258                         }
7259                 }
7260
7261                 for (i = 0; i < num_drivers; i++) {
7262                         DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7263
7264                         result = winreg_get_driver(mem_ctx, session_info,
7265                                                    msg_ctx,
7266                                                    architecture, drivers[i],
7267                                                    version, &driver);
7268                         if (!W_ERROR_IS_OK(result)) {
7269                                 goto out;
7270                         }
7271
7272                         switch (level) {
7273                         case 1:
7274                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
7275                                                                    driver, servername);
7276                                 break;
7277                         case 2:
7278                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
7279                                                                    driver, servername);
7280                                 break;
7281                         case 3:
7282                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
7283                                                                    driver, servername);
7284                                 break;
7285                         case 4:
7286                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
7287                                                                    driver, servername);
7288                                 break;
7289                         case 5:
7290                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
7291                                                                    driver, servername);
7292                                 break;
7293                         case 6:
7294                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
7295                                                                    driver, servername);
7296                                 break;
7297                         case 8:
7298                                 result = fill_printer_driver_info8(info, &info[count+i].info8,
7299                                                                    driver, servername);
7300                                 break;
7301                         default:
7302                                 result = WERR_UNKNOWN_LEVEL;
7303                                 break;
7304                         }
7305
7306                         TALLOC_FREE(driver);
7307
7308                         if (!W_ERROR_IS_OK(result)) {
7309                                 goto out;
7310                         }
7311                 }
7312
7313                 count += num_drivers;
7314                 TALLOC_FREE(drivers);
7315         }
7316
7317  out:
7318         TALLOC_FREE(drivers);
7319
7320         if (!W_ERROR_IS_OK(result)) {
7321                 TALLOC_FREE(info);
7322                 return result;
7323         }
7324
7325         *info_p = info;
7326         *count_p = count;
7327
7328         return WERR_OK;
7329 }
7330
7331 /****************************************************************************
7332  Enumerates all printer drivers by level.
7333 ****************************************************************************/
7334
7335 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7336                                        const struct auth_serversupplied_info *session_info,
7337                                        struct messaging_context *msg_ctx,
7338                                        const char *servername,
7339                                        const char *architecture,
7340                                        uint32_t level,
7341                                        union spoolss_DriverInfo **info_p,
7342                                        uint32_t *count_p)
7343 {
7344         uint32_t a,i;
7345         WERROR result = WERR_OK;
7346
7347         if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7348
7349                 for (a=0; archi_table[a].long_archi != NULL; a++) {
7350
7351                         union spoolss_DriverInfo *info = NULL;
7352                         uint32_t count = 0;
7353
7354                         result = enumprinterdrivers_level_by_architecture(mem_ctx,
7355                                                                           session_info,
7356                                                                           msg_ctx,
7357                                                                           servername,
7358                                                                           archi_table[a].long_archi,
7359                                                                           level,
7360                                                                           &info,
7361                                                                           &count);
7362                         if (!W_ERROR_IS_OK(result)) {
7363                                 continue;
7364                         }
7365
7366                         for (i=0; i < count; i++) {
7367                                 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7368                                              info[i], info_p, count_p);
7369                         }
7370                 }
7371
7372                 return result;
7373         }
7374
7375         return enumprinterdrivers_level_by_architecture(mem_ctx,
7376                                                         session_info,
7377                                                         msg_ctx,
7378                                                         servername,
7379                                                         architecture,
7380                                                         level,
7381                                                         info_p,
7382                                                         count_p);
7383 }
7384
7385 /****************************************************************
7386  _spoolss_EnumPrinterDrivers
7387 ****************************************************************/
7388
7389 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7390                                    struct spoolss_EnumPrinterDrivers *r)
7391 {
7392         const char *cservername;
7393         WERROR result;
7394
7395         /* that's an [in out] buffer */
7396
7397         if (!r->in.buffer && (r->in.offered != 0)) {
7398                 return WERR_INVALID_PARAM;
7399         }
7400
7401         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7402
7403         *r->out.needed = 0;
7404         *r->out.count = 0;
7405         *r->out.info = NULL;
7406
7407         cservername = canon_servername(r->in.server);
7408
7409         if (!is_myname_or_ipaddr(cservername)) {
7410                 return WERR_UNKNOWN_PRINTER_DRIVER;
7411         }
7412
7413         result = enumprinterdrivers_level(p->mem_ctx,
7414                                           get_session_info_system(),
7415                                           p->msg_ctx,
7416                                           cservername,
7417                                           r->in.environment,
7418                                           r->in.level,
7419                                           r->out.info,
7420                                           r->out.count);
7421         if (!W_ERROR_IS_OK(result)) {
7422                 return result;
7423         }
7424
7425         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7426                                                      spoolss_EnumPrinterDrivers,
7427                                                      *r->out.info, r->in.level,
7428                                                      *r->out.count);
7429         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7430         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7431
7432         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7433 }
7434
7435 /****************************************************************
7436  _spoolss_EnumForms
7437 ****************************************************************/
7438
7439 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7440                           struct spoolss_EnumForms *r)
7441 {
7442         WERROR result;
7443
7444         *r->out.count = 0;
7445         *r->out.needed = 0;
7446         *r->out.info = NULL;
7447
7448         /* that's an [in out] buffer */
7449
7450         if (!r->in.buffer && (r->in.offered != 0) ) {
7451                 return WERR_INVALID_PARAM;
7452         }
7453
7454         DEBUG(4,("_spoolss_EnumForms\n"));
7455         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7456         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7457
7458         switch (r->in.level) {
7459         case 1:
7460                 result = winreg_printer_enumforms1(p->mem_ctx,
7461                                                    get_session_info_system(),
7462                                                    p->msg_ctx,
7463                                                    r->out.count,
7464                                                    r->out.info);
7465                 break;
7466         default:
7467                 result = WERR_UNKNOWN_LEVEL;
7468                 break;
7469         }
7470
7471         if (!W_ERROR_IS_OK(result)) {
7472                 return result;
7473         }
7474
7475         if (*r->out.count == 0) {
7476                 return WERR_NO_MORE_ITEMS;
7477         }
7478
7479         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7480                                                      spoolss_EnumForms,
7481                                                      *r->out.info, r->in.level,
7482                                                      *r->out.count);
7483         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7484         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7485
7486         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7487 }
7488
7489 /****************************************************************
7490  _spoolss_GetForm
7491 ****************************************************************/
7492
7493 WERROR _spoolss_GetForm(struct pipes_struct *p,
7494                         struct spoolss_GetForm *r)
7495 {
7496         WERROR result;
7497
7498         /* that's an [in out] buffer */
7499
7500         if (!r->in.buffer && (r->in.offered != 0)) {
7501                 return WERR_INVALID_PARAM;
7502         }
7503
7504         DEBUG(4,("_spoolss_GetForm\n"));
7505         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7506         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7507
7508         switch (r->in.level) {
7509         case 1:
7510                 result = winreg_printer_getform1(p->mem_ctx,
7511                                                  get_session_info_system(),
7512                                                  p->msg_ctx,
7513                                                  r->in.form_name,
7514                                                  &r->out.info->info1);
7515                 break;
7516         default:
7517                 result = WERR_UNKNOWN_LEVEL;
7518                 break;
7519         }
7520
7521         if (!W_ERROR_IS_OK(result)) {
7522                 TALLOC_FREE(r->out.info);
7523                 return result;
7524         }
7525
7526         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
7527                                                r->out.info, r->in.level);
7528         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7529
7530         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7531 }
7532
7533 /****************************************************************************
7534 ****************************************************************************/
7535
7536 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7537                           struct spoolss_PortInfo1 *r,
7538                           const char *name)
7539 {
7540         r->port_name = talloc_strdup(mem_ctx, name);
7541         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7542
7543         return WERR_OK;
7544 }
7545
7546 /****************************************************************************
7547  TODO: This probably needs distinguish between TCP/IP and Local ports
7548  somehow.
7549 ****************************************************************************/
7550
7551 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7552                           struct spoolss_PortInfo2 *r,
7553                           const char *name)
7554 {
7555         r->port_name = talloc_strdup(mem_ctx, name);
7556         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7557
7558         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7559         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7560
7561         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7562         W_ERROR_HAVE_NO_MEMORY(r->description);
7563
7564         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7565         r->reserved = 0;
7566
7567         return WERR_OK;
7568 }
7569
7570
7571 /****************************************************************************
7572  wrapper around the enumer ports command
7573 ****************************************************************************/
7574
7575 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7576 {
7577         char *cmd = lp_enumports_cmd();
7578         char **qlines = NULL;
7579         char *command = NULL;
7580         int numlines;
7581         int ret;
7582         int fd;
7583
7584         *count = 0;
7585         *lines = NULL;
7586
7587         /* if no hook then just fill in the default port */
7588
7589         if ( !*cmd ) {
7590                 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7591                         return WERR_NOMEM;
7592                 }
7593                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7594                         TALLOC_FREE(qlines);
7595                         return WERR_NOMEM;
7596                 }
7597                 qlines[1] = NULL;
7598                 numlines = 1;
7599         }
7600         else {
7601                 /* we have a valid enumport command */
7602
7603                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7604                 if (!command) {
7605                         return WERR_NOMEM;
7606                 }
7607
7608                 DEBUG(10,("Running [%s]\n", command));
7609                 ret = smbrun(command, &fd);
7610                 DEBUG(10,("Returned [%d]\n", ret));
7611                 TALLOC_FREE(command);
7612                 if (ret != 0) {
7613                         if (fd != -1) {
7614                                 close(fd);
7615                         }
7616                         return WERR_ACCESS_DENIED;
7617                 }
7618
7619                 numlines = 0;
7620                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7621                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7622                 close(fd);
7623         }
7624
7625         *count = numlines;
7626         *lines = qlines;
7627
7628         return WERR_OK;
7629 }
7630
7631 /****************************************************************************
7632  enumports level 1.
7633 ****************************************************************************/
7634
7635 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7636                                 union spoolss_PortInfo **info_p,
7637                                 uint32_t *count)
7638 {
7639         union spoolss_PortInfo *info = NULL;
7640         int i=0;
7641         WERROR result = WERR_OK;
7642         char **qlines = NULL;
7643         int numlines = 0;
7644
7645         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7646         if (!W_ERROR_IS_OK(result)) {
7647                 goto out;
7648         }
7649
7650         if (numlines) {
7651                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7652                 if (!info) {
7653                         DEBUG(10,("Returning WERR_NOMEM\n"));
7654                         result = WERR_NOMEM;
7655                         goto out;
7656                 }
7657
7658                 for (i=0; i<numlines; i++) {
7659                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7660                         result = fill_port_1(info, &info[i].info1, qlines[i]);
7661                         if (!W_ERROR_IS_OK(result)) {
7662                                 goto out;
7663                         }
7664                 }
7665         }
7666         TALLOC_FREE(qlines);
7667
7668 out:
7669         if (!W_ERROR_IS_OK(result)) {
7670                 TALLOC_FREE(info);
7671                 TALLOC_FREE(qlines);
7672                 *count = 0;
7673                 *info_p = NULL;
7674                 return result;
7675         }
7676
7677         *info_p = info;
7678         *count = numlines;
7679
7680         return WERR_OK;
7681 }
7682
7683 /****************************************************************************
7684  enumports level 2.
7685 ****************************************************************************/
7686
7687 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7688                                 union spoolss_PortInfo **info_p,
7689                                 uint32_t *count)
7690 {
7691         union spoolss_PortInfo *info = NULL;
7692         int i=0;
7693         WERROR result = WERR_OK;
7694         char **qlines = NULL;
7695         int numlines = 0;
7696
7697         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7698         if (!W_ERROR_IS_OK(result)) {
7699                 goto out;
7700         }
7701
7702         if (numlines) {
7703                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7704                 if (!info) {
7705                         DEBUG(10,("Returning WERR_NOMEM\n"));
7706                         result = WERR_NOMEM;
7707                         goto out;
7708                 }
7709
7710                 for (i=0; i<numlines; i++) {
7711                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7712                         result = fill_port_2(info, &info[i].info2, qlines[i]);
7713                         if (!W_ERROR_IS_OK(result)) {
7714                                 goto out;
7715                         }
7716                 }
7717         }
7718         TALLOC_FREE(qlines);
7719
7720 out:
7721         if (!W_ERROR_IS_OK(result)) {
7722                 TALLOC_FREE(info);
7723                 TALLOC_FREE(qlines);
7724                 *count = 0;
7725                 *info_p = NULL;
7726                 return result;
7727         }
7728
7729         *info_p = info;
7730         *count = numlines;
7731
7732         return WERR_OK;
7733 }
7734
7735 /****************************************************************
7736  _spoolss_EnumPorts
7737 ****************************************************************/
7738
7739 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
7740                           struct spoolss_EnumPorts *r)
7741 {
7742         WERROR result;
7743
7744         /* that's an [in out] buffer */
7745
7746         if (!r->in.buffer && (r->in.offered != 0)) {
7747                 return WERR_INVALID_PARAM;
7748         }
7749
7750         DEBUG(4,("_spoolss_EnumPorts\n"));
7751
7752         *r->out.count = 0;
7753         *r->out.needed = 0;
7754         *r->out.info = NULL;
7755
7756         switch (r->in.level) {
7757         case 1:
7758                 result = enumports_level_1(p->mem_ctx, r->out.info,
7759                                            r->out.count);
7760                 break;
7761         case 2:
7762                 result = enumports_level_2(p->mem_ctx, r->out.info,
7763                                            r->out.count);
7764                 break;
7765         default:
7766                 return WERR_UNKNOWN_LEVEL;
7767         }
7768
7769         if (!W_ERROR_IS_OK(result)) {
7770                 return result;
7771         }
7772
7773         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7774                                                      spoolss_EnumPorts,
7775                                                      *r->out.info, r->in.level,
7776                                                      *r->out.count);
7777         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7778         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7779
7780         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7781 }
7782
7783 /****************************************************************************
7784 ****************************************************************************/
7785
7786 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
7787                                            const char *server,
7788                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
7789                                            struct spoolss_DeviceMode *devmode,
7790                                            struct security_descriptor *secdesc,
7791                                            struct spoolss_UserLevelCtr *user_ctr,
7792                                            struct policy_handle *handle)
7793 {
7794         struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
7795         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
7796         int     snum;
7797         WERROR err = WERR_OK;
7798
7799         /* samba does not have a concept of local, non-shared printers yet, so
7800          * make sure we always setup sharename - gd */
7801         if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
7802             (info2->printername != NULL && info2->printername[0] != '\0')) {
7803                 DEBUG(5, ("spoolss_addprinterex_level_2: "
7804                         "no sharename has been set, setting printername %s as sharename\n",
7805                         info2->printername));
7806                 info2->sharename = info2->printername;
7807         }
7808
7809         /* check to see if the printer already exists */
7810         if ((snum = print_queue_snum(info2->sharename)) != -1) {
7811                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7812                         info2->sharename));
7813                 return WERR_PRINTER_ALREADY_EXISTS;
7814         }
7815
7816         if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7817                 if ((snum = print_queue_snum(info2->printername)) != -1) {
7818                         DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7819                                 info2->printername));
7820                         return WERR_PRINTER_ALREADY_EXISTS;
7821                 }
7822         }
7823
7824         /* validate printer info struct */
7825         if (!info2->printername || strlen(info2->printername) == 0) {
7826                 return WERR_INVALID_PRINTER_NAME;
7827         }
7828         if (!info2->portname || strlen(info2->portname) == 0) {
7829                 return WERR_UNKNOWN_PORT;
7830         }
7831         if (!info2->drivername || strlen(info2->drivername) == 0) {
7832                 return WERR_UNKNOWN_PRINTER_DRIVER;
7833         }
7834         if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
7835                 return WERR_UNKNOWN_PRINTPROCESSOR;
7836         }
7837
7838         /* FIXME!!!  smbd should check to see if the driver is installed before
7839            trying to add a printer like this  --jerry */
7840
7841         if (*lp_addprinter_cmd() ) {
7842                 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
7843                                        info2, p->client_id->addr,
7844                                        p->msg_ctx) ) {
7845                         return WERR_ACCESS_DENIED;
7846                 }
7847         } else {
7848                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7849                         "smb.conf parameter \"addprinter command\" is defined. This"
7850                         "parameter must exist for this call to succeed\n",
7851                         info2->sharename ));
7852         }
7853
7854         if ((snum = print_queue_snum(info2->sharename)) == -1) {
7855                 return WERR_ACCESS_DENIED;
7856         }
7857
7858         /* you must be a printer admin to add a new printer */
7859         if (!print_access_check(p->session_info,
7860                                 p->msg_ctx,
7861                                 snum,
7862                                 PRINTER_ACCESS_ADMINISTER)) {
7863                 return WERR_ACCESS_DENIED;
7864         }
7865
7866         /*
7867          * Do sanity check on the requested changes for Samba.
7868          */
7869
7870         if (!check_printer_ok(p->mem_ctx, info2, snum)) {
7871                 return WERR_INVALID_PARAM;
7872         }
7873
7874         if (devmode == NULL) {
7875                 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
7876         }
7877
7878         update_dsspooler(p->mem_ctx,
7879                          get_session_info_system(),
7880                          p->msg_ctx,
7881                          0,
7882                          info2,
7883                          NULL);
7884
7885         err = winreg_update_printer(p->mem_ctx,
7886                                     get_session_info_system(),
7887                                     p->msg_ctx,
7888                                     info2->sharename,
7889                                     info2_mask,
7890                                     info2,
7891                                     devmode,
7892                                     secdesc);
7893         if (!W_ERROR_IS_OK(err)) {
7894                 return err;
7895         }
7896
7897         err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
7898         if (!W_ERROR_IS_OK(err)) {
7899                 /* Handle open failed - remove addition. */
7900                 ZERO_STRUCTP(handle);
7901                 return err;
7902         }
7903
7904         return WERR_OK;
7905 }
7906
7907 /****************************************************************
7908  _spoolss_AddPrinterEx
7909 ****************************************************************/
7910
7911 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
7912                              struct spoolss_AddPrinterEx *r)
7913 {
7914         switch (r->in.info_ctr->level) {
7915         case 1:
7916                 /* we don't handle yet */
7917                 /* but I know what to do ... */
7918                 return WERR_UNKNOWN_LEVEL;
7919         case 2:
7920                 return spoolss_addprinterex_level_2(p, r->in.server,
7921                                                     r->in.info_ctr,
7922                                                     r->in.devmode_ctr->devmode,
7923                                                     r->in.secdesc_ctr->sd,
7924                                                     r->in.userlevel_ctr,
7925                                                     r->out.handle);
7926         default:
7927                 return WERR_UNKNOWN_LEVEL;
7928         }
7929 }
7930
7931 /****************************************************************
7932  _spoolss_AddPrinter
7933 ****************************************************************/
7934
7935 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
7936                            struct spoolss_AddPrinter *r)
7937 {
7938         struct spoolss_AddPrinterEx a;
7939         struct spoolss_UserLevelCtr userlevel_ctr;
7940
7941         ZERO_STRUCT(userlevel_ctr);
7942
7943         userlevel_ctr.level = 1;
7944
7945         a.in.server             = r->in.server;
7946         a.in.info_ctr           = r->in.info_ctr;
7947         a.in.devmode_ctr        = r->in.devmode_ctr;
7948         a.in.secdesc_ctr        = r->in.secdesc_ctr;
7949         a.in.userlevel_ctr      = &userlevel_ctr;
7950         a.out.handle            = r->out.handle;
7951
7952         return _spoolss_AddPrinterEx(p, &a);
7953 }
7954
7955 /****************************************************************
7956  _spoolss_AddPrinterDriverEx
7957 ****************************************************************/
7958
7959 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
7960                                    struct spoolss_AddPrinterDriverEx *r)
7961 {
7962         WERROR err = WERR_OK;
7963         const char *driver_name = NULL;
7964         uint32_t version;
7965         const char *fn;
7966
7967         switch (p->opnum) {
7968                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7969                         fn = "_spoolss_AddPrinterDriver";
7970                         break;
7971                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7972                         fn = "_spoolss_AddPrinterDriverEx";
7973                         break;
7974                 default:
7975                         return WERR_INVALID_PARAM;
7976         }
7977
7978         /*
7979          * we only support the semantics of AddPrinterDriver()
7980          * i.e. only copy files that are newer than existing ones
7981          */
7982
7983         if (r->in.flags == 0) {
7984                 return WERR_INVALID_PARAM;
7985         }
7986
7987         if (r->in.flags != APD_COPY_NEW_FILES) {
7988                 return WERR_ACCESS_DENIED;
7989         }
7990
7991         /* FIXME */
7992         if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
7993                 /* Clever hack from Martin Zielinski <mz@seh.de>
7994                  * to allow downgrade from level 8 (Vista).
7995                  */
7996                 DEBUG(0,("%s: level %d not yet implemented\n", fn,
7997                         r->in.info_ctr->level));
7998                 return WERR_UNKNOWN_LEVEL;
7999         }
8000
8001         DEBUG(5,("Cleaning driver's information\n"));
8002         err = clean_up_driver_struct(p->mem_ctx, p, r->in.info_ctr);
8003         if (!W_ERROR_IS_OK(err))
8004                 goto done;
8005
8006         DEBUG(5,("Moving driver to final destination\n"));
8007         err = move_driver_to_download_area(p, r->in.info_ctr);
8008         if (!W_ERROR_IS_OK(err)) {
8009                 goto done;
8010         }
8011
8012         err = winreg_add_driver(p->mem_ctx,
8013                                 get_session_info_system(),
8014                                 p->msg_ctx,
8015                                 r->in.info_ctr,
8016                                 &driver_name,
8017                                 &version);
8018         if (!W_ERROR_IS_OK(err)) {
8019                 goto done;
8020         }
8021
8022         /*
8023          * I think this is where he DrvUpgradePrinter() hook would be
8024          * be called in a driver's interface DLL on a Windows NT 4.0/2k
8025          * server.  Right now, we just need to send ourselves a message
8026          * to update each printer bound to this driver.   --jerry
8027          */
8028
8029         if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8030                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8031                         fn, driver_name));
8032         }
8033
8034 done:
8035         return err;
8036 }
8037
8038 /****************************************************************
8039  _spoolss_AddPrinterDriver
8040 ****************************************************************/
8041
8042 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8043                                  struct spoolss_AddPrinterDriver *r)
8044 {
8045         struct spoolss_AddPrinterDriverEx a;
8046
8047         switch (r->in.info_ctr->level) {
8048         case 2:
8049         case 3:
8050         case 4:
8051         case 5:
8052                 break;
8053         default:
8054                 return WERR_UNKNOWN_LEVEL;
8055         }
8056
8057         a.in.servername         = r->in.servername;
8058         a.in.info_ctr           = r->in.info_ctr;
8059         a.in.flags              = APD_COPY_NEW_FILES;
8060
8061         return _spoolss_AddPrinterDriverEx(p, &a);
8062 }
8063
8064 /****************************************************************************
8065 ****************************************************************************/
8066
8067 struct _spoolss_paths {
8068         int type;
8069         const char *share;
8070         const char *dir;
8071 };
8072
8073 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8074
8075 static const struct _spoolss_paths spoolss_paths[]= {
8076         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
8077         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
8078 };
8079
8080 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8081                                           const char *servername,
8082                                           const char *environment,
8083                                           int component,
8084                                           char **path)
8085 {
8086         const char *pservername = NULL;
8087         const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
8088         const char *short_archi;
8089
8090         *path = NULL;
8091
8092         /* environment may be empty */
8093         if (environment && strlen(environment)) {
8094                 long_archi = environment;
8095         }
8096
8097         /* servername may be empty */
8098         if (servername && strlen(servername)) {
8099                 pservername = canon_servername(servername);
8100
8101                 if (!is_myname_or_ipaddr(pservername)) {
8102                         return WERR_INVALID_PARAM;
8103                 }
8104         }
8105
8106         if (!(short_archi = get_short_archi(long_archi))) {
8107                 return WERR_INVALID_ENVIRONMENT;
8108         }
8109
8110         switch (component) {
8111         case SPOOLSS_PRTPROCS_PATH:
8112         case SPOOLSS_DRIVER_PATH:
8113                 if (pservername) {
8114                         *path = talloc_asprintf(mem_ctx,
8115                                         "\\\\%s\\%s\\%s",
8116                                         pservername,
8117                                         spoolss_paths[component].share,
8118                                         short_archi);
8119                 } else {
8120                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8121                                         SPOOLSS_DEFAULT_SERVER_PATH,
8122                                         spoolss_paths[component].dir,
8123                                         short_archi);
8124                 }
8125                 break;
8126         default:
8127                 return WERR_INVALID_PARAM;
8128         }
8129
8130         if (!*path) {
8131                 return WERR_NOMEM;
8132         }
8133
8134         return WERR_OK;
8135 }
8136
8137 /****************************************************************************
8138 ****************************************************************************/
8139
8140 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8141                                           const char *servername,
8142                                           const char *environment,
8143                                           struct spoolss_DriverDirectoryInfo1 *r)
8144 {
8145         WERROR werr;
8146         char *path = NULL;
8147
8148         werr = compose_spoolss_server_path(mem_ctx,
8149                                            servername,
8150                                            environment,
8151                                            SPOOLSS_DRIVER_PATH,
8152                                            &path);
8153         if (!W_ERROR_IS_OK(werr)) {
8154                 return werr;
8155         }
8156
8157         DEBUG(4,("printer driver directory: [%s]\n", path));
8158
8159         r->directory_name = path;
8160
8161         return WERR_OK;
8162 }
8163
8164 /****************************************************************
8165  _spoolss_GetPrinterDriverDirectory
8166 ****************************************************************/
8167
8168 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8169                                           struct spoolss_GetPrinterDriverDirectory *r)
8170 {
8171         WERROR werror;
8172
8173         /* that's an [in out] buffer */
8174
8175         if (!r->in.buffer && (r->in.offered != 0)) {
8176                 return WERR_INVALID_PARAM;
8177         }
8178
8179         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8180                 r->in.level));
8181
8182         *r->out.needed = 0;
8183
8184         /* r->in.level is ignored */
8185
8186         werror = getprinterdriverdir_level_1(p->mem_ctx,
8187                                              r->in.server,
8188                                              r->in.environment,
8189                                              &r->out.info->info1);
8190         if (!W_ERROR_IS_OK(werror)) {
8191                 TALLOC_FREE(r->out.info);
8192                 return werror;
8193         }
8194
8195         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8196                                                r->out.info, r->in.level);
8197         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8198
8199         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8200 }
8201
8202 /****************************************************************
8203  _spoolss_EnumPrinterData
8204 ****************************************************************/
8205
8206 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8207                                 struct spoolss_EnumPrinterData *r)
8208 {
8209         WERROR result;
8210         struct spoolss_EnumPrinterDataEx r2;
8211         uint32_t count;
8212         struct spoolss_PrinterEnumValues *info, *val = NULL;
8213         uint32_t needed;
8214
8215         r2.in.handle    = r->in.handle;
8216         r2.in.key_name  = "PrinterDriverData";
8217         r2.in.offered   = 0;
8218         r2.out.count    = &count;
8219         r2.out.info     = &info;
8220         r2.out.needed   = &needed;
8221
8222         result = _spoolss_EnumPrinterDataEx(p, &r2);
8223         if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8224                 r2.in.offered = needed;
8225                 result = _spoolss_EnumPrinterDataEx(p, &r2);
8226         }
8227         if (!W_ERROR_IS_OK(result)) {
8228                 return result;
8229         }
8230
8231         /*
8232          * The NT machine wants to know the biggest size of value and data
8233          *
8234          * cf: MSDN EnumPrinterData remark section
8235          */
8236
8237         if (!r->in.value_offered && !r->in.data_offered) {
8238                 uint32_t biggest_valuesize = 0;
8239                 uint32_t biggest_datasize = 0;
8240                 int i, name_length;
8241
8242                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8243
8244                 for (i=0; i<count; i++) {
8245
8246                         name_length = strlen(info[i].value_name);
8247                         if (strlen(info[i].value_name) > biggest_valuesize) {
8248                                 biggest_valuesize = name_length;
8249                         }
8250
8251                         if (info[i].data_length > biggest_datasize) {
8252                                 biggest_datasize = info[i].data_length;
8253                         }
8254
8255                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8256                                 biggest_datasize));
8257                 }
8258
8259                 /* the value is an UNICODE string but real_value_size is the length
8260                    in bytes including the trailing 0 */
8261
8262                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8263                 *r->out.data_needed  = biggest_datasize;
8264
8265                 DEBUG(6,("final values: [%d], [%d]\n",
8266                         *r->out.value_needed, *r->out.data_needed));
8267
8268                 return WERR_OK;
8269         }
8270
8271         if (r->in.enum_index < count) {
8272                 val = &info[r->in.enum_index];
8273         }
8274
8275         if (val == NULL) {
8276                 /* out_value should default to "" or else NT4 has
8277                    problems unmarshalling the response */
8278
8279                 if (r->in.value_offered) {
8280                         *r->out.value_needed = 1;
8281                         r->out.value_name = talloc_strdup(r, "");
8282                         if (!r->out.value_name) {
8283                                 return WERR_NOMEM;
8284                         }
8285                 } else {
8286                         r->out.value_name = NULL;
8287                         *r->out.value_needed = 0;
8288                 }
8289
8290                 /* the data is counted in bytes */
8291
8292                 *r->out.data_needed = r->in.data_offered;
8293
8294                 result = WERR_NO_MORE_ITEMS;
8295         } else {
8296                 /*
8297                  * the value is:
8298                  * - counted in bytes in the request
8299                  * - counted in UNICODE chars in the max reply
8300                  * - counted in bytes in the real size
8301                  *
8302                  * take a pause *before* coding not *during* coding
8303                  */
8304
8305                 /* name */
8306                 if (r->in.value_offered) {
8307                         r->out.value_name = talloc_strdup(r, val->value_name);
8308                         if (!r->out.value_name) {
8309                                 return WERR_NOMEM;
8310                         }
8311                         *r->out.value_needed = val->value_name_len;
8312                 } else {
8313                         r->out.value_name = NULL;
8314                         *r->out.value_needed = 0;
8315                 }
8316
8317                 /* type */
8318
8319                 *r->out.type = val->type;
8320
8321                 /* data - counted in bytes */
8322
8323                 /*
8324                  * See the section "Dynamically Typed Query Parameters"
8325                  * in MS-RPRN.
8326                  */
8327
8328                 if (r->out.data && val->data && val->data->data &&
8329                                 val->data_length && r->in.data_offered) {
8330                         memcpy(r->out.data, val->data->data,
8331                                 MIN(val->data_length,r->in.data_offered));
8332                 }
8333
8334                 *r->out.data_needed = val->data_length;
8335
8336                 result = WERR_OK;
8337         }
8338
8339         return result;
8340 }
8341
8342 /****************************************************************
8343  _spoolss_SetPrinterData
8344 ****************************************************************/
8345
8346 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8347                                struct spoolss_SetPrinterData *r)
8348 {
8349         struct spoolss_SetPrinterDataEx r2;
8350
8351         r2.in.handle            = r->in.handle;
8352         r2.in.key_name          = "PrinterDriverData";
8353         r2.in.value_name        = r->in.value_name;
8354         r2.in.type              = r->in.type;
8355         r2.in.data              = r->in.data;
8356         r2.in.offered           = r->in.offered;
8357
8358         return _spoolss_SetPrinterDataEx(p, &r2);
8359 }
8360
8361 /****************************************************************
8362  _spoolss_ResetPrinter
8363 ****************************************************************/
8364
8365 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8366                              struct spoolss_ResetPrinter *r)
8367 {
8368         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8369         int             snum;
8370
8371         DEBUG(5,("_spoolss_ResetPrinter\n"));
8372
8373         /*
8374          * All we do is to check to see if the handle and queue is valid.
8375          * This call really doesn't mean anything to us because we only
8376          * support RAW printing.   --jerry
8377          */
8378
8379         if (!Printer) {
8380                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8381                         OUR_HANDLE(r->in.handle)));
8382                 return WERR_BADFID;
8383         }
8384
8385         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8386                 return WERR_BADFID;
8387
8388
8389         /* blindly return success */
8390         return WERR_OK;
8391 }
8392
8393 /****************************************************************
8394  _spoolss_DeletePrinterData
8395 ****************************************************************/
8396
8397 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8398                                   struct spoolss_DeletePrinterData *r)
8399 {
8400         struct spoolss_DeletePrinterDataEx r2;
8401
8402         r2.in.handle            = r->in.handle;
8403         r2.in.key_name          = "PrinterDriverData";
8404         r2.in.value_name        = r->in.value_name;
8405
8406         return _spoolss_DeletePrinterDataEx(p, &r2);
8407 }
8408
8409 /****************************************************************
8410  _spoolss_AddForm
8411 ****************************************************************/
8412
8413 WERROR _spoolss_AddForm(struct pipes_struct *p,
8414                         struct spoolss_AddForm *r)
8415 {
8416         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8417         int snum = -1;
8418         WERROR status = WERR_OK;
8419
8420         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8421
8422         DEBUG(5,("_spoolss_AddForm\n"));
8423
8424         if (!Printer) {
8425                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8426                         OUR_HANDLE(r->in.handle)));
8427                 return WERR_BADFID;
8428         }
8429
8430         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8431            and not a printer admin, then fail */
8432
8433         if ((p->session_info->utok.uid != sec_initial_uid()) &&
8434             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8435             !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8436                                           p->session_info->info3->base.domain.string,
8437                                           NULL,
8438                                           p->session_info->security_token,
8439                                           lp_printer_admin(snum))) {
8440                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8441                 return WERR_ACCESS_DENIED;
8442         }
8443
8444         switch (form->flags) {
8445         case SPOOLSS_FORM_USER:
8446         case SPOOLSS_FORM_BUILTIN:
8447         case SPOOLSS_FORM_PRINTER:
8448                 break;
8449         default:
8450                 return WERR_INVALID_PARAM;
8451         }
8452
8453         status = winreg_printer_addform1(p->mem_ctx,
8454                                          get_session_info_system(),
8455                                          p->msg_ctx,
8456                                          form);
8457         if (!W_ERROR_IS_OK(status)) {
8458                 return status;
8459         }
8460
8461         /*
8462          * ChangeID must always be set if this is a printer
8463          */
8464         if (Printer->printer_type == SPLHND_PRINTER) {
8465                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8466                         return WERR_BADFID;
8467                 }
8468
8469                 status = winreg_printer_update_changeid(p->mem_ctx,
8470                                                         get_session_info_system(),
8471                                                         p->msg_ctx,
8472                                                         lp_const_servicename(snum));
8473                 if (!W_ERROR_IS_OK(status)) {
8474                         return status;
8475                 }
8476         }
8477
8478         return status;
8479 }
8480
8481 /****************************************************************
8482  _spoolss_DeleteForm
8483 ****************************************************************/
8484
8485 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8486                            struct spoolss_DeleteForm *r)
8487 {
8488         const char *form_name = r->in.form_name;
8489         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8490         int snum = -1;
8491         WERROR status = WERR_OK;
8492
8493         DEBUG(5,("_spoolss_DeleteForm\n"));
8494
8495         if (!Printer) {
8496                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8497                         OUR_HANDLE(r->in.handle)));
8498                 return WERR_BADFID;
8499         }
8500
8501         if ((p->session_info->utok.uid != sec_initial_uid()) &&
8502             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8503             !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8504                                           p->session_info->info3->base.domain.string,
8505                                           NULL,
8506                                           p->session_info->security_token,
8507                                           lp_printer_admin(snum))) {
8508                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8509                 return WERR_ACCESS_DENIED;
8510         }
8511
8512         status = winreg_printer_deleteform1(p->mem_ctx,
8513                                             get_session_info_system(),
8514                                             p->msg_ctx,
8515                                             form_name);
8516         if (!W_ERROR_IS_OK(status)) {
8517                 return status;
8518         }
8519
8520         /*
8521          * ChangeID must always be set if this is a printer
8522          */
8523         if (Printer->printer_type == SPLHND_PRINTER) {
8524                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8525                         return WERR_BADFID;
8526                 }
8527
8528                 status = winreg_printer_update_changeid(p->mem_ctx,
8529                                                         get_session_info_system(),
8530                                                         p->msg_ctx,
8531                                                         lp_const_servicename(snum));
8532                 if (!W_ERROR_IS_OK(status)) {
8533                         return status;
8534                 }
8535         }
8536
8537         return status;
8538 }
8539
8540 /****************************************************************
8541  _spoolss_SetForm
8542 ****************************************************************/
8543
8544 WERROR _spoolss_SetForm(struct pipes_struct *p,
8545                         struct spoolss_SetForm *r)
8546 {
8547         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8548         const char *form_name = r->in.form_name;
8549         int snum = -1;
8550         WERROR status = WERR_OK;
8551
8552         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8553
8554         DEBUG(5,("_spoolss_SetForm\n"));
8555
8556         if (!Printer) {
8557                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8558                         OUR_HANDLE(r->in.handle)));
8559                 return WERR_BADFID;
8560         }
8561
8562         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8563            and not a printer admin, then fail */
8564
8565         if ((p->session_info->utok.uid != sec_initial_uid()) &&
8566              !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8567              !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8568                                           p->session_info->info3->base.domain.string,
8569                                           NULL,
8570                                           p->session_info->security_token,
8571                                           lp_printer_admin(snum))) {
8572                 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8573                 return WERR_ACCESS_DENIED;
8574         }
8575
8576         status = winreg_printer_setform1(p->mem_ctx,
8577                                          get_session_info_system(),
8578                                          p->msg_ctx,
8579                                          form_name,
8580                                          form);
8581         if (!W_ERROR_IS_OK(status)) {
8582                 return status;
8583         }
8584
8585         /*
8586          * ChangeID must always be set if this is a printer
8587          */
8588         if (Printer->printer_type == SPLHND_PRINTER) {
8589                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8590                         return WERR_BADFID;
8591                 }
8592
8593                 status = winreg_printer_update_changeid(p->mem_ctx,
8594                                                         get_session_info_system(),
8595                                                         p->msg_ctx,
8596                                                         lp_const_servicename(snum));
8597                 if (!W_ERROR_IS_OK(status)) {
8598                         return status;
8599                 }
8600         }
8601
8602         return status;
8603 }
8604
8605 /****************************************************************************
8606  fill_print_processor1
8607 ****************************************************************************/
8608
8609 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8610                                     struct spoolss_PrintProcessorInfo1 *r,
8611                                     const char *print_processor_name)
8612 {
8613         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8614         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8615
8616         return WERR_OK;
8617 }
8618
8619 /****************************************************************************
8620  enumprintprocessors level 1.
8621 ****************************************************************************/
8622
8623 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8624                                           union spoolss_PrintProcessorInfo **info_p,
8625                                           uint32_t *count)
8626 {
8627         union spoolss_PrintProcessorInfo *info;
8628         WERROR result;
8629
8630         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8631         W_ERROR_HAVE_NO_MEMORY(info);
8632
8633         *count = 1;
8634
8635         result = fill_print_processor1(info, &info[0].info1, "winprint");
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_EnumPrintProcessors
8654 ****************************************************************/
8655
8656 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
8657                                     struct spoolss_EnumPrintProcessors *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_EnumPrintProcessors\n"));
8668
8669         /*
8670          * Enumerate the print processors ...
8671          *
8672          * Just reply with "winprint", 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         if (!get_short_archi(r->in.environment)) {
8681                 return WERR_INVALID_ENVIRONMENT;
8682         }
8683
8684         switch (r->in.level) {
8685         case 1:
8686                 result = enumprintprocessors_level_1(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_EnumPrintProcessors,
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  fill_printprocdatatype1
8709 ****************************************************************************/
8710
8711 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8712                                       struct spoolss_PrintProcDataTypesInfo1 *r,
8713                                       const char *name_array)
8714 {
8715         r->name_array = talloc_strdup(mem_ctx, name_array);
8716         W_ERROR_HAVE_NO_MEMORY(r->name_array);
8717
8718         return WERR_OK;
8719 }
8720
8721 /****************************************************************************
8722  enumprintprocdatatypes level 1.
8723 ****************************************************************************/
8724
8725 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8726                                              union spoolss_PrintProcDataTypesInfo **info_p,
8727                                              uint32_t *count)
8728 {
8729         WERROR result;
8730         union spoolss_PrintProcDataTypesInfo *info;
8731
8732         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8733         W_ERROR_HAVE_NO_MEMORY(info);
8734
8735         *count = 1;
8736
8737         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8738         if (!W_ERROR_IS_OK(result)) {
8739                 goto out;
8740         }
8741
8742  out:
8743         if (!W_ERROR_IS_OK(result)) {
8744                 TALLOC_FREE(info);
8745                 *count = 0;
8746                 return result;
8747         }
8748
8749         *info_p = info;
8750
8751         return WERR_OK;
8752 }
8753
8754 /****************************************************************
8755  _spoolss_EnumPrintProcDataTypes
8756 ****************************************************************/
8757
8758 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
8759                                        struct spoolss_EnumPrintProcDataTypes *r)
8760 {
8761         WERROR result;
8762
8763         /* that's an [in out] buffer */
8764
8765         if (!r->in.buffer && (r->in.offered != 0)) {
8766                 return WERR_INVALID_PARAM;
8767         }
8768
8769         DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8770
8771         *r->out.count = 0;
8772         *r->out.needed = 0;
8773         *r->out.info = NULL;
8774
8775         if (r->in.print_processor_name == NULL ||
8776             !strequal(r->in.print_processor_name, "winprint")) {
8777                 return WERR_UNKNOWN_PRINTPROCESSOR;
8778         }
8779
8780         switch (r->in.level) {
8781         case 1:
8782                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8783                                                         r->out.count);
8784                 break;
8785         default:
8786                 return WERR_UNKNOWN_LEVEL;
8787         }
8788
8789         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8790                                                      spoolss_EnumPrintProcDataTypes,
8791                                                      *r->out.info, r->in.level,
8792                                                      *r->out.count);
8793         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8794         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8795
8796         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8797 }
8798
8799 /****************************************************************************
8800  fill_monitor_1
8801 ****************************************************************************/
8802
8803 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8804                              struct spoolss_MonitorInfo1 *r,
8805                              const char *monitor_name)
8806 {
8807         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8808         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8809
8810         return WERR_OK;
8811 }
8812
8813 /****************************************************************************
8814  fill_monitor_2
8815 ****************************************************************************/
8816
8817 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8818                              struct spoolss_MonitorInfo2 *r,
8819                              const char *monitor_name,
8820                              const char *environment,
8821                              const char *dll_name)
8822 {
8823         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8824         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8825         r->environment                  = talloc_strdup(mem_ctx, environment);
8826         W_ERROR_HAVE_NO_MEMORY(r->environment);
8827         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
8828         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8829
8830         return WERR_OK;
8831 }
8832
8833 /****************************************************************************
8834  enumprintmonitors level 1.
8835 ****************************************************************************/
8836
8837 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8838                                         union spoolss_MonitorInfo **info_p,
8839                                         uint32_t *count)
8840 {
8841         union spoolss_MonitorInfo *info;
8842         WERROR result = WERR_OK;
8843
8844         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8845         W_ERROR_HAVE_NO_MEMORY(info);
8846
8847         *count = 2;
8848
8849         result = fill_monitor_1(info, &info[0].info1,
8850                                 SPL_LOCAL_PORT);
8851         if (!W_ERROR_IS_OK(result)) {
8852                 goto out;
8853         }
8854
8855         result = fill_monitor_1(info, &info[1].info1,
8856                                 SPL_TCPIP_PORT);
8857         if (!W_ERROR_IS_OK(result)) {
8858                 goto out;
8859         }
8860
8861 out:
8862         if (!W_ERROR_IS_OK(result)) {
8863                 TALLOC_FREE(info);
8864                 *count = 0;
8865                 return result;
8866         }
8867
8868         *info_p = info;
8869
8870         return WERR_OK;
8871 }
8872
8873 /****************************************************************************
8874  enumprintmonitors level 2.
8875 ****************************************************************************/
8876
8877 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8878                                         union spoolss_MonitorInfo **info_p,
8879                                         uint32_t *count)
8880 {
8881         union spoolss_MonitorInfo *info;
8882         WERROR result = WERR_OK;
8883
8884         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8885         W_ERROR_HAVE_NO_MEMORY(info);
8886
8887         *count = 2;
8888
8889         result = fill_monitor_2(info, &info[0].info2,
8890                                 SPL_LOCAL_PORT,
8891                                 "Windows NT X86", /* FIXME */
8892                                 "localmon.dll");
8893         if (!W_ERROR_IS_OK(result)) {
8894                 goto out;
8895         }
8896
8897         result = fill_monitor_2(info, &info[1].info2,
8898                                 SPL_TCPIP_PORT,
8899                                 "Windows NT X86", /* FIXME */
8900                                 "tcpmon.dll");
8901         if (!W_ERROR_IS_OK(result)) {
8902                 goto out;
8903         }
8904
8905 out:
8906         if (!W_ERROR_IS_OK(result)) {
8907                 TALLOC_FREE(info);
8908                 *count = 0;
8909                 return result;
8910         }
8911
8912         *info_p = info;
8913
8914         return WERR_OK;
8915 }
8916
8917 /****************************************************************
8918  _spoolss_EnumMonitors
8919 ****************************************************************/
8920
8921 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
8922                              struct spoolss_EnumMonitors *r)
8923 {
8924         WERROR result;
8925
8926         /* that's an [in out] buffer */
8927
8928         if (!r->in.buffer && (r->in.offered != 0)) {
8929                 return WERR_INVALID_PARAM;
8930         }
8931
8932         DEBUG(5,("_spoolss_EnumMonitors\n"));
8933
8934         /*
8935          * Enumerate the print monitors ...
8936          *
8937          * Just reply with "Local Port", to keep NT happy
8938          * and I can use my nice printer checker.
8939          */
8940
8941         *r->out.count = 0;
8942         *r->out.needed = 0;
8943         *r->out.info = NULL;
8944
8945         switch (r->in.level) {
8946         case 1:
8947                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8948                                                    r->out.count);
8949                 break;
8950         case 2:
8951                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8952                                                    r->out.count);
8953                 break;
8954         default:
8955                 return WERR_UNKNOWN_LEVEL;
8956         }
8957
8958         if (!W_ERROR_IS_OK(result)) {
8959                 return result;
8960         }
8961
8962         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8963                                                      spoolss_EnumMonitors,
8964                                                      *r->out.info, r->in.level,
8965                                                      *r->out.count);
8966         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8967         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8968
8969         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8970 }
8971
8972 /****************************************************************************
8973 ****************************************************************************/
8974
8975 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8976                              const print_queue_struct *queue,
8977                              int count, int snum,
8978                              struct spoolss_PrinterInfo2 *pinfo2,
8979                              uint32_t jobid,
8980                              struct spoolss_JobInfo1 *r)
8981 {
8982         int i = 0;
8983         bool found = false;
8984
8985         for (i=0; i<count; i++) {
8986                 if (queue[i].job == (int)jobid) {
8987                         found = true;
8988                         break;
8989                 }
8990         }
8991
8992         if (found == false) {
8993                 /* NT treats not found as bad param... yet another bad choice */
8994                 return WERR_INVALID_PARAM;
8995         }
8996
8997         return fill_job_info1(mem_ctx,
8998                               r,
8999                               &queue[i],
9000                               i,
9001                               snum,
9002                               pinfo2);
9003 }
9004
9005 /****************************************************************************
9006 ****************************************************************************/
9007
9008 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9009                              const print_queue_struct *queue,
9010                              int count, int snum,
9011                              struct spoolss_PrinterInfo2 *pinfo2,
9012                              uint32_t jobid,
9013                              struct spoolss_JobInfo2 *r)
9014 {
9015         int i = 0;
9016         bool found = false;
9017         struct spoolss_DeviceMode *devmode;
9018         WERROR result;
9019
9020         for (i=0; i<count; i++) {
9021                 if (queue[i].job == (int)jobid) {
9022                         found = true;
9023                         break;
9024                 }
9025         }
9026
9027         if (found == false) {
9028                 /* NT treats not found as bad param... yet another bad
9029                    choice */
9030                 return WERR_INVALID_PARAM;
9031         }
9032
9033         /*
9034          * if the print job does not have a DEVMODE associated with it,
9035          * just use the one for the printer. A NULL devicemode is not
9036          *  a failure condition
9037          */
9038
9039         devmode = print_job_devmode(lp_const_servicename(snum), jobid);
9040         if (!devmode) {
9041                 result = spoolss_create_default_devmode(mem_ctx,
9042                                                 pinfo2->printername,
9043                                                 &devmode);
9044                 if (!W_ERROR_IS_OK(result)) {
9045                         DEBUG(3, ("Can't proceed w/o a devmode!"));
9046                         return result;
9047                 }
9048         }
9049
9050         return fill_job_info2(mem_ctx,
9051                               r,
9052                               &queue[i],
9053                               i,
9054                               snum,
9055                               pinfo2,
9056                               devmode);
9057 }
9058
9059 /****************************************************************
9060  _spoolss_GetJob
9061 ****************************************************************/
9062
9063 WERROR _spoolss_GetJob(struct pipes_struct *p,
9064                        struct spoolss_GetJob *r)
9065 {
9066         WERROR result = WERR_OK;
9067         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9068         int snum;
9069         int count;
9070         print_queue_struct      *queue = NULL;
9071         print_status_struct prt_status;
9072
9073         /* that's an [in out] buffer */
9074
9075         if (!r->in.buffer && (r->in.offered != 0)) {
9076                 return WERR_INVALID_PARAM;
9077         }
9078
9079         DEBUG(5,("_spoolss_GetJob\n"));
9080
9081         *r->out.needed = 0;
9082
9083         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9084                 return WERR_BADFID;
9085         }
9086
9087         result = winreg_get_printer(p->mem_ctx,
9088                                     get_session_info_system(),
9089                                     p->msg_ctx,
9090                                     lp_const_servicename(snum),
9091                                     &pinfo2);
9092         if (!W_ERROR_IS_OK(result)) {
9093                 return result;
9094         }
9095
9096         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9097
9098         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9099                      count, prt_status.status, prt_status.message));
9100
9101         switch (r->in.level) {
9102         case 1:
9103                 result = getjob_level_1(p->mem_ctx,
9104                                         queue, count, snum, pinfo2,
9105                                         r->in.job_id, &r->out.info->info1);
9106                 break;
9107         case 2:
9108                 result = getjob_level_2(p->mem_ctx,
9109                                         queue, count, snum, pinfo2,
9110                                         r->in.job_id, &r->out.info->info2);
9111                 break;
9112         default:
9113                 result = WERR_UNKNOWN_LEVEL;
9114                 break;
9115         }
9116
9117         SAFE_FREE(queue);
9118         TALLOC_FREE(pinfo2);
9119
9120         if (!W_ERROR_IS_OK(result)) {
9121                 TALLOC_FREE(r->out.info);
9122                 return result;
9123         }
9124
9125         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9126                                                                                    r->in.level);
9127         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9128
9129         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9130 }
9131
9132 /****************************************************************
9133  _spoolss_GetPrinterDataEx
9134 ****************************************************************/
9135
9136 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9137                                  struct spoolss_GetPrinterDataEx *r)
9138 {
9139
9140         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9141         const char *printer;
9142         int                     snum = 0;
9143         WERROR result = WERR_OK;
9144         DATA_BLOB blob;
9145         enum winreg_Type val_type;
9146         uint8_t *val_data;
9147         uint32_t val_size;
9148
9149
9150         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9151
9152         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9153                 r->in.key_name, r->in.value_name));
9154
9155         /* in case of problem, return some default values */
9156
9157         *r->out.needed  = 0;
9158         *r->out.type    = REG_NONE;
9159
9160         if (!Printer) {
9161                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9162                         OUR_HANDLE(r->in.handle)));
9163                 result = WERR_BADFID;
9164                 goto done;
9165         }
9166
9167         /* Is the handle to a printer or to the server? */
9168
9169         if (Printer->printer_type == SPLHND_SERVER) {
9170
9171                 union spoolss_PrinterData data;
9172
9173                 result = getprinterdata_printer_server(p->mem_ctx,
9174                                                        r->in.value_name,
9175                                                        r->out.type,
9176                                                        &data);
9177                 if (!W_ERROR_IS_OK(result)) {
9178                         return result;
9179                 }
9180
9181                 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
9182                                                   *r->out.type, &data);
9183                 if (!W_ERROR_IS_OK(result)) {
9184                         return result;
9185                 }
9186
9187                 *r->out.needed = blob.length;
9188
9189                 if (r->in.offered >= *r->out.needed) {
9190                         memcpy(r->out.data, blob.data, blob.length);
9191                 }
9192
9193                 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9194         }
9195
9196         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9197                 return WERR_BADFID;
9198         }
9199         printer = lp_const_servicename(snum);
9200
9201         /* check to see if the keyname is valid */
9202         if (!strlen(r->in.key_name)) {
9203                 return WERR_INVALID_PARAM;
9204         }
9205
9206         /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9207         if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9208             strequal(r->in.value_name, "ChangeId")) {
9209                 *r->out.type = REG_DWORD;
9210                 *r->out.needed = 4;
9211                 if (r->in.offered >= *r->out.needed) {
9212                         uint32_t changeid = 0;
9213
9214                         result = winreg_printer_get_changeid(p->mem_ctx,
9215                                                              get_session_info_system(),
9216                                                              p->msg_ctx,
9217                                                              printer,
9218                                                              &changeid);
9219                         if (!W_ERROR_IS_OK(result)) {
9220                                 return result;
9221                         }
9222
9223                         SIVAL(r->out.data, 0, changeid);
9224                         result = WERR_OK;
9225                 }
9226                 goto done;
9227         }
9228
9229         result = winreg_get_printer_dataex(p->mem_ctx,
9230                                            get_session_info_system(),
9231                                            p->msg_ctx,
9232                                            printer,
9233                                            r->in.key_name,
9234                                            r->in.value_name,
9235                                            &val_type,
9236                                            &val_data,
9237                                            &val_size);
9238         if (!W_ERROR_IS_OK(result)) {
9239                 return result;
9240         }
9241
9242         *r->out.needed = val_size;
9243         *r->out.type = val_type;
9244
9245         if (r->in.offered >= *r->out.needed) {
9246                 memcpy(r->out.data, val_data, val_size);
9247         }
9248
9249  done:
9250         /* retain type when returning WERR_MORE_DATA */
9251         r->out.data     = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
9252
9253         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9254 }
9255
9256 /****************************************************************
9257  _spoolss_SetPrinterDataEx
9258 ****************************************************************/
9259
9260 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9261                                  struct spoolss_SetPrinterDataEx *r)
9262 {
9263         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9264         int                     snum = 0;
9265         WERROR                  result = WERR_OK;
9266         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9267         char                    *oid_string;
9268
9269         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9270
9271         /* From MSDN documentation of SetPrinterDataEx: pass request to
9272            SetPrinterData if key is "PrinterDriverData" */
9273
9274         if (!Printer) {
9275                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9276                         OUR_HANDLE(r->in.handle)));
9277                 return WERR_BADFID;
9278         }
9279
9280         if (Printer->printer_type == SPLHND_SERVER) {
9281                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9282                         "Not implemented for server handles yet\n"));
9283                 return WERR_INVALID_PARAM;
9284         }
9285
9286         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9287                 return WERR_BADFID;
9288         }
9289
9290         /*
9291          * Access check : NT returns "access denied" if you make a
9292          * SetPrinterData call without the necessary privildge.
9293          * we were originally returning OK if nothing changed
9294          * which made Win2k issue **a lot** of SetPrinterData
9295          * when connecting to a printer  --jerry
9296          */
9297
9298         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9299                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9300                         "change denied by handle access permissions\n"));
9301                 return WERR_ACCESS_DENIED;
9302         }
9303
9304         result = winreg_get_printer(Printer,
9305                                     get_session_info_system(),
9306                                     p->msg_ctx,
9307                                     lp_servicename(snum),
9308                                     &pinfo2);
9309         if (!W_ERROR_IS_OK(result)) {
9310                 return result;
9311         }
9312
9313         /* check for OID in valuename */
9314
9315         oid_string = strchr(r->in.value_name, ',');
9316         if (oid_string) {
9317                 *oid_string = '\0';
9318                 oid_string++;
9319         }
9320
9321         /* save the registry data */
9322
9323         result = winreg_set_printer_dataex(p->mem_ctx,
9324                                            get_session_info_system(),
9325                                            p->msg_ctx,
9326                                            pinfo2->sharename,
9327                                            r->in.key_name,
9328                                            r->in.value_name,
9329                                            r->in.type,
9330                                            r->in.data,
9331                                            r->in.offered);
9332
9333         if (W_ERROR_IS_OK(result)) {
9334                 /* save the OID if one was specified */
9335                 if (oid_string) {
9336                         char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9337                                 r->in.key_name, SPOOL_OID_KEY);
9338                         if (!str) {
9339                                 result = WERR_NOMEM;
9340                                 goto done;
9341                         }
9342
9343                         /*
9344                          * I'm not checking the status here on purpose.  Don't know
9345                          * if this is right, but I'm returning the status from the
9346                          * previous set_printer_dataex() call.  I have no idea if
9347                          * this is right.    --jerry
9348                          */
9349                         winreg_set_printer_dataex(p->mem_ctx,
9350                                                   get_session_info_system(),
9351                                                   p->msg_ctx,
9352                                                   pinfo2->sharename,
9353                                                   str,
9354                                                   r->in.value_name,
9355                                                   REG_SZ,
9356                                                   (uint8_t *) oid_string,
9357                                                   strlen(oid_string) + 1);
9358                 }
9359
9360                 result = winreg_printer_update_changeid(p->mem_ctx,
9361                                                         get_session_info_system(),
9362                                                         p->msg_ctx,
9363                                                         lp_const_servicename(snum));
9364
9365         }
9366
9367 done:
9368         talloc_free(pinfo2);
9369         return result;
9370 }
9371
9372 /****************************************************************
9373  _spoolss_DeletePrinterDataEx
9374 ****************************************************************/
9375
9376 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9377                                     struct spoolss_DeletePrinterDataEx *r)
9378 {
9379         const char *printer;
9380         int             snum=0;
9381         WERROR          status = WERR_OK;
9382         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9383
9384         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9385
9386         if (!Printer) {
9387                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9388                         "Invalid handle (%s:%u:%u).\n",
9389                         OUR_HANDLE(r->in.handle)));
9390                 return WERR_BADFID;
9391         }
9392
9393         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9394                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9395                         "printer properties change denied by handle\n"));
9396                 return WERR_ACCESS_DENIED;
9397         }
9398
9399         if (!r->in.value_name || !r->in.key_name) {
9400                 return WERR_NOMEM;
9401         }
9402
9403         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9404                 return WERR_BADFID;
9405         }
9406         printer = lp_const_servicename(snum);
9407
9408         status = winreg_delete_printer_dataex(p->mem_ctx,
9409                                               get_session_info_system(),
9410                                               p->msg_ctx,
9411                                               printer,
9412                                               r->in.key_name,
9413                                               r->in.value_name);
9414         if (W_ERROR_IS_OK(status)) {
9415                 status = winreg_printer_update_changeid(p->mem_ctx,
9416                                                         get_session_info_system(),
9417                                                         p->msg_ctx,
9418                                                         printer);
9419         }
9420
9421         return status;
9422 }
9423
9424 /****************************************************************
9425  _spoolss_EnumPrinterKey
9426 ****************************************************************/
9427
9428 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9429                                struct spoolss_EnumPrinterKey *r)
9430 {
9431         uint32_t        num_keys;
9432         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9433         int             snum = 0;
9434         WERROR          result = WERR_BADFILE;
9435         const char **array = NULL;
9436         DATA_BLOB blob;
9437
9438         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9439
9440         if (!Printer) {
9441                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9442                         OUR_HANDLE(r->in.handle)));
9443                 return WERR_BADFID;
9444         }
9445
9446         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9447                 return WERR_BADFID;
9448         }
9449
9450         result = winreg_enum_printer_key(p->mem_ctx,
9451                                          get_session_info_system(),
9452                                          p->msg_ctx,
9453                                          lp_const_servicename(snum),
9454                                          r->in.key_name,
9455                                          &num_keys,
9456                                          &array);
9457         if (!W_ERROR_IS_OK(result)) {
9458                 goto done;
9459         }
9460
9461         if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9462                 result = WERR_NOMEM;
9463                 goto done;
9464         }
9465
9466         *r->out._ndr_size = r->in.offered / 2;
9467         *r->out.needed = blob.length;
9468
9469         if (r->in.offered < *r->out.needed) {
9470                 result = WERR_MORE_DATA;
9471         } else {
9472                 result = WERR_OK;
9473                 r->out.key_buffer->string_array = array;
9474         }
9475
9476  done:
9477         if (!W_ERROR_IS_OK(result)) {
9478                 TALLOC_FREE(array);
9479                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9480                         *r->out.needed = 0;
9481                 }
9482         }
9483
9484         return result;
9485 }
9486
9487 /****************************************************************
9488  _spoolss_DeletePrinterKey
9489 ****************************************************************/
9490
9491 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9492                                  struct spoolss_DeletePrinterKey *r)
9493 {
9494         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9495         int                     snum=0;
9496         WERROR                  status;
9497         const char *printer;
9498
9499         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9500
9501         if (!Printer) {
9502                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9503                         OUR_HANDLE(r->in.handle)));
9504                 return WERR_BADFID;
9505         }
9506
9507         /* if keyname == NULL, return error */
9508         if ( !r->in.key_name )
9509                 return WERR_INVALID_PARAM;
9510
9511         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9512                 return WERR_BADFID;
9513         }
9514
9515         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9516                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9517                         "printer properties change denied by handle\n"));
9518                 return WERR_ACCESS_DENIED;
9519         }
9520
9521         printer = lp_const_servicename(snum);
9522
9523         /* delete the key and all subkeys */
9524         status = winreg_delete_printer_key(p->mem_ctx,
9525                                            get_session_info_system(),
9526                                            p->msg_ctx,
9527                                            printer,
9528                                            r->in.key_name);
9529         if (W_ERROR_IS_OK(status)) {
9530                 status = winreg_printer_update_changeid(p->mem_ctx,
9531                                                         get_session_info_system(),
9532                                                         p->msg_ctx,
9533                                                         printer);
9534         }
9535
9536         return status;
9537 }
9538
9539 /****************************************************************
9540  _spoolss_EnumPrinterDataEx
9541 ****************************************************************/
9542
9543 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
9544                                   struct spoolss_EnumPrinterDataEx *r)
9545 {
9546         uint32_t        count = 0;
9547         struct spoolss_PrinterEnumValues *info = NULL;
9548         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9549         int             snum;
9550         WERROR          result;
9551
9552         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9553
9554         *r->out.count = 0;
9555         *r->out.needed = 0;
9556         *r->out.info = NULL;
9557
9558         if (!Printer) {
9559                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9560                         OUR_HANDLE(r->in.handle)));
9561                 return WERR_BADFID;
9562         }
9563
9564         /*
9565          * first check for a keyname of NULL or "".  Win2k seems to send
9566          * this a lot and we should send back WERR_INVALID_PARAM
9567          * no need to spend time looking up the printer in this case.
9568          * --jerry
9569          */
9570
9571         if (!strlen(r->in.key_name)) {
9572                 result = WERR_INVALID_PARAM;
9573                 goto done;
9574         }
9575
9576         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9577                 return WERR_BADFID;
9578         }
9579
9580         /* now look for a match on the key name */
9581         result = winreg_enum_printer_dataex(p->mem_ctx,
9582                                             get_session_info_system(),
9583                                             p->msg_ctx,
9584                                             lp_const_servicename(snum),
9585                                             r->in.key_name,
9586                                             &count,
9587                                             &info);
9588         if (!W_ERROR_IS_OK(result)) {
9589                 goto done;
9590         }
9591
9592 #if 0 /* FIXME - gd */
9593         /* housekeeping information in the reply */
9594
9595         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9596          * the hand marshalled container size is a multiple
9597          * of 4 bytes for RPC alignment.
9598          */
9599
9600         if (needed % 4) {
9601                 needed += 4-(needed % 4);
9602         }
9603 #endif
9604         *r->out.count   = count;
9605         *r->out.info    = info;
9606
9607  done:
9608         if (!W_ERROR_IS_OK(result)) {
9609                 return result;
9610         }
9611
9612         *r->out.needed  = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9613                                                spoolss_EnumPrinterDataEx,
9614                                                *r->out.info,
9615                                                *r->out.count);
9616         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9617         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9618
9619         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9620 }
9621
9622 /****************************************************************************
9623 ****************************************************************************/
9624
9625 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9626                                                  const char *servername,
9627                                                  const char *environment,
9628                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
9629 {
9630         WERROR werr;
9631         char *path = NULL;
9632
9633         werr = compose_spoolss_server_path(mem_ctx,
9634                                            servername,
9635                                            environment,
9636                                            SPOOLSS_PRTPROCS_PATH,
9637                                            &path);
9638         if (!W_ERROR_IS_OK(werr)) {
9639                 return werr;
9640         }
9641
9642         DEBUG(4,("print processor directory: [%s]\n", path));
9643
9644         r->directory_name = path;
9645
9646         return WERR_OK;
9647 }
9648
9649 /****************************************************************
9650  _spoolss_GetPrintProcessorDirectory
9651 ****************************************************************/
9652
9653 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
9654                                            struct spoolss_GetPrintProcessorDirectory *r)
9655 {
9656         WERROR result;
9657         char *prnproc_share = NULL;
9658         bool prnproc_share_exists = false;
9659         int snum;
9660
9661         /* that's an [in out] buffer */
9662
9663         if (!r->in.buffer && (r->in.offered != 0)) {
9664                 return WERR_INVALID_PARAM;
9665         }
9666
9667         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9668                 r->in.level));
9669
9670         *r->out.needed = 0;
9671
9672         /* r->in.level is ignored */
9673
9674         /* We always should reply with a local print processor directory so that
9675          * users are not forced to have a [prnproc$] share on the Samba spoolss
9676          * server, if users decide to do so, lets announce it though - Guenther */
9677
9678         snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
9679         if (!prnproc_share) {
9680                 return WERR_NOMEM;
9681         }
9682         if (snum != -1) {
9683                 prnproc_share_exists = true;
9684         }
9685
9686         result = getprintprocessordirectory_level_1(p->mem_ctx,
9687                                                     prnproc_share_exists ? r->in.server : NULL,
9688                                                     r->in.environment,
9689                                                     &r->out.info->info1);
9690         if (!W_ERROR_IS_OK(result)) {
9691                 TALLOC_FREE(r->out.info);
9692                 return result;
9693         }
9694
9695         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
9696                                                                                    r->out.info, r->in.level);
9697         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9698
9699         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9700 }
9701
9702 /*******************************************************************
9703  ********************************************************************/
9704
9705 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9706                                const char *dllname)
9707 {
9708         enum ndr_err_code ndr_err;
9709         struct spoolss_MonitorUi ui;
9710
9711         ui.dll_name = dllname;
9712
9713         ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
9714                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9715         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9716                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9717         }
9718         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9719 }
9720
9721 /*******************************************************************
9722  Streams the monitor UI DLL name in UNICODE
9723 *******************************************************************/
9724
9725 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9726                                struct security_token *token, DATA_BLOB *in,
9727                                DATA_BLOB *out, uint32_t *needed)
9728 {
9729         const char *dllname = "tcpmonui.dll";
9730
9731         *needed = (strlen(dllname)+1) * 2;
9732
9733         if (out->length < *needed) {
9734                 return WERR_INSUFFICIENT_BUFFER;
9735         }
9736
9737         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9738                 return WERR_NOMEM;
9739         }
9740
9741         return WERR_OK;
9742 }
9743
9744 /*******************************************************************
9745  ********************************************************************/
9746
9747 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9748                              struct spoolss_PortData1 *port1,
9749                              const DATA_BLOB *buf)
9750 {
9751         enum ndr_err_code ndr_err;
9752         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
9753                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9754         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9755                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9756         }
9757         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9758 }
9759
9760 /*******************************************************************
9761  ********************************************************************/
9762
9763 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9764                              struct spoolss_PortData2 *port2,
9765                              const DATA_BLOB *buf)
9766 {
9767         enum ndr_err_code ndr_err;
9768         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
9769                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9770         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9771                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9772         }
9773         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9774 }
9775
9776 /*******************************************************************
9777  Create a new TCP/IP port
9778 *******************************************************************/
9779
9780 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9781                              struct security_token *token, DATA_BLOB *in,
9782                              DATA_BLOB *out, uint32_t *needed)
9783 {
9784         struct spoolss_PortData1 port1;
9785         struct spoolss_PortData2 port2;
9786         char *device_uri = NULL;
9787         uint32_t version;
9788
9789         const char *portname;
9790         const char *hostaddress;
9791         const char *queue;
9792         uint32_t port_number;
9793         uint32_t protocol;
9794
9795         /* peek for spoolss_PortData version */
9796
9797         if (!in || (in->length < (128 + 4))) {
9798                 return WERR_GENERAL_FAILURE;
9799         }
9800
9801         version = IVAL(in->data, 128);
9802
9803         switch (version) {
9804                 case 1:
9805                         ZERO_STRUCT(port1);
9806
9807                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
9808                                 return WERR_NOMEM;
9809                         }
9810
9811                         portname        = port1.portname;
9812                         hostaddress     = port1.hostaddress;
9813                         queue           = port1.queue;
9814                         protocol        = port1.protocol;
9815                         port_number     = port1.port_number;
9816
9817                         break;
9818                 case 2:
9819                         ZERO_STRUCT(port2);
9820
9821                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
9822                                 return WERR_NOMEM;
9823                         }
9824
9825                         portname        = port2.portname;
9826                         hostaddress     = port2.hostaddress;
9827                         queue           = port2.queue;
9828                         protocol        = port2.protocol;
9829                         port_number     = port2.port_number;
9830
9831                         break;
9832                 default:
9833                         DEBUG(1,("xcvtcp_addport: "
9834                                 "unknown version of port_data: %d\n", version));
9835                         return WERR_UNKNOWN_PORT;
9836         }
9837
9838         /* create the device URI and call the add_port_hook() */
9839
9840         switch (protocol) {
9841         case PROTOCOL_RAWTCP_TYPE:
9842                 device_uri = talloc_asprintf(mem_ctx,
9843                                 "socket://%s:%d/", hostaddress,
9844                                 port_number);
9845                 break;
9846
9847         case PROTOCOL_LPR_TYPE:
9848                 device_uri = talloc_asprintf(mem_ctx,
9849                         "lpr://%s/%s", hostaddress, queue );
9850                 break;
9851
9852         default:
9853                 return WERR_UNKNOWN_PORT;
9854         }
9855
9856         if (!device_uri) {
9857                 return WERR_NOMEM;
9858         }
9859
9860         return add_port_hook(mem_ctx, token, portname, device_uri);
9861 }
9862
9863 /*******************************************************************
9864 *******************************************************************/
9865
9866 struct xcv_api_table xcvtcp_cmds[] = {
9867         { "MonitorUI",  xcvtcp_monitorui },
9868         { "AddPort",    xcvtcp_addport},
9869         { NULL,         NULL }
9870 };
9871
9872 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9873                                      struct security_token *token, const char *command,
9874                                      DATA_BLOB *inbuf,
9875                                      DATA_BLOB *outbuf,
9876                                      uint32_t *needed )
9877 {
9878         int i;
9879
9880         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9881
9882         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9883                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9884                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9885         }
9886
9887         return WERR_BADFUNC;
9888 }
9889
9890 /*******************************************************************
9891 *******************************************************************/
9892 #if 0   /* don't support management using the "Local Port" monitor */
9893
9894 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9895                                  struct security_token *token, DATA_BLOB *in,
9896                                  DATA_BLOB *out, uint32_t *needed)
9897 {
9898         const char *dllname = "localui.dll";
9899
9900         *needed = (strlen(dllname)+1) * 2;
9901
9902         if (out->length < *needed) {
9903                 return WERR_INSUFFICIENT_BUFFER;
9904         }
9905
9906         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9907                 return WERR_NOMEM;
9908         }
9909
9910         return WERR_OK;
9911 }
9912
9913 /*******************************************************************
9914 *******************************************************************/
9915
9916 struct xcv_api_table xcvlocal_cmds[] = {
9917         { "MonitorUI",  xcvlocal_monitorui },
9918         { NULL,         NULL }
9919 };
9920 #else
9921 struct xcv_api_table xcvlocal_cmds[] = {
9922         { NULL,         NULL }
9923 };
9924 #endif
9925
9926
9927
9928 /*******************************************************************
9929 *******************************************************************/
9930
9931 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9932                                        struct security_token *token, const char *command,
9933                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9934                                        uint32_t *needed)
9935 {
9936         int i;
9937
9938         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9939
9940         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9941                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9942                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9943         }
9944         return WERR_BADFUNC;
9945 }
9946
9947 /****************************************************************
9948  _spoolss_XcvData
9949 ****************************************************************/
9950
9951 WERROR _spoolss_XcvData(struct pipes_struct *p,
9952                         struct spoolss_XcvData *r)
9953 {
9954         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9955         DATA_BLOB out_data = data_blob_null;
9956         WERROR werror;
9957
9958         if (!Printer) {
9959                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9960                         OUR_HANDLE(r->in.handle)));
9961                 return WERR_BADFID;
9962         }
9963
9964         /* Has to be a handle to the TCP/IP port monitor */
9965
9966         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9967                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9968                 return WERR_BADFID;
9969         }
9970
9971         /* requires administrative access to the server */
9972
9973         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9974                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9975                 return WERR_ACCESS_DENIED;
9976         }
9977
9978         /* Allocate the outgoing buffer */
9979
9980         if (r->in.out_data_size) {
9981                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9982                 if (out_data.data == NULL) {
9983                         return WERR_NOMEM;
9984                 }
9985         }
9986
9987         switch ( Printer->printer_type ) {
9988         case SPLHND_PORTMON_TCP:
9989                 werror = process_xcvtcp_command(p->mem_ctx,
9990                                                 p->session_info->security_token,
9991                                                 r->in.function_name,
9992                                                 &r->in.in_data, &out_data,
9993                                                 r->out.needed);
9994                 break;
9995         case SPLHND_PORTMON_LOCAL:
9996                 werror = process_xcvlocal_command(p->mem_ctx,
9997                                                   p->session_info->security_token,
9998                                                   r->in.function_name,
9999                                                   &r->in.in_data, &out_data,
10000                                                   r->out.needed);
10001                 break;
10002         default:
10003                 werror = WERR_INVALID_PRINT_MONITOR;
10004         }
10005
10006         if (!W_ERROR_IS_OK(werror)) {
10007                 return werror;
10008         }
10009
10010         *r->out.status_code = 0;
10011
10012         if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10013                 memcpy(r->out.out_data, out_data.data,
10014                         MIN(r->in.out_data_size, out_data.length));
10015         }
10016
10017         return WERR_OK;
10018 }
10019
10020 /****************************************************************
10021  _spoolss_AddPrintProcessor
10022 ****************************************************************/
10023
10024 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10025                                   struct spoolss_AddPrintProcessor *r)
10026 {
10027         /* for now, just indicate success and ignore the add.  We'll
10028            automatically set the winprint processor for printer
10029            entries later.  Used to debug the LexMark Optra S 1855 PCL
10030            driver --jerry */
10031
10032         return WERR_OK;
10033 }
10034
10035 /****************************************************************
10036  _spoolss_AddPort
10037 ****************************************************************/
10038
10039 WERROR _spoolss_AddPort(struct pipes_struct *p,
10040                         struct spoolss_AddPort *r)
10041 {
10042         /* do what w2k3 does */
10043
10044         return WERR_NOT_SUPPORTED;
10045 }
10046
10047 /****************************************************************
10048  _spoolss_GetPrinterDriver
10049 ****************************************************************/
10050
10051 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10052                                  struct spoolss_GetPrinterDriver *r)
10053 {
10054         p->rng_fault_state = true;
10055         return WERR_NOT_SUPPORTED;
10056 }
10057
10058 /****************************************************************
10059  _spoolss_ReadPrinter
10060 ****************************************************************/
10061
10062 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10063                             struct spoolss_ReadPrinter *r)
10064 {
10065         p->rng_fault_state = true;
10066         return WERR_NOT_SUPPORTED;
10067 }
10068
10069 /****************************************************************
10070  _spoolss_WaitForPrinterChange
10071 ****************************************************************/
10072
10073 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10074                                      struct spoolss_WaitForPrinterChange *r)
10075 {
10076         p->rng_fault_state = true;
10077         return WERR_NOT_SUPPORTED;
10078 }
10079
10080 /****************************************************************
10081  _spoolss_ConfigurePort
10082 ****************************************************************/
10083
10084 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10085                               struct spoolss_ConfigurePort *r)
10086 {
10087         p->rng_fault_state = true;
10088         return WERR_NOT_SUPPORTED;
10089 }
10090
10091 /****************************************************************
10092  _spoolss_DeletePort
10093 ****************************************************************/
10094
10095 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10096                            struct spoolss_DeletePort *r)
10097 {
10098         p->rng_fault_state = true;
10099         return WERR_NOT_SUPPORTED;
10100 }
10101
10102 /****************************************************************
10103  _spoolss_CreatePrinterIC
10104 ****************************************************************/
10105
10106 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10107                                 struct spoolss_CreatePrinterIC *r)
10108 {
10109         p->rng_fault_state = true;
10110         return WERR_NOT_SUPPORTED;
10111 }
10112
10113 /****************************************************************
10114  _spoolss_PlayGDIScriptOnPrinterIC
10115 ****************************************************************/
10116
10117 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10118                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
10119 {
10120         p->rng_fault_state = true;
10121         return WERR_NOT_SUPPORTED;
10122 }
10123
10124 /****************************************************************
10125  _spoolss_DeletePrinterIC
10126 ****************************************************************/
10127
10128 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10129                                 struct spoolss_DeletePrinterIC *r)
10130 {
10131         p->rng_fault_state = true;
10132         return WERR_NOT_SUPPORTED;
10133 }
10134
10135 /****************************************************************
10136  _spoolss_AddPrinterConnection
10137 ****************************************************************/
10138
10139 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10140                                      struct spoolss_AddPrinterConnection *r)
10141 {
10142         p->rng_fault_state = true;
10143         return WERR_NOT_SUPPORTED;
10144 }
10145
10146 /****************************************************************
10147  _spoolss_DeletePrinterConnection
10148 ****************************************************************/
10149
10150 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10151                                         struct spoolss_DeletePrinterConnection *r)
10152 {
10153         p->rng_fault_state = true;
10154         return WERR_NOT_SUPPORTED;
10155 }
10156
10157 /****************************************************************
10158  _spoolss_PrinterMessageBox
10159 ****************************************************************/
10160
10161 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10162                                   struct spoolss_PrinterMessageBox *r)
10163 {
10164         p->rng_fault_state = true;
10165         return WERR_NOT_SUPPORTED;
10166 }
10167
10168 /****************************************************************
10169  _spoolss_AddMonitor
10170 ****************************************************************/
10171
10172 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10173                            struct spoolss_AddMonitor *r)
10174 {
10175         p->rng_fault_state = true;
10176         return WERR_NOT_SUPPORTED;
10177 }
10178
10179 /****************************************************************
10180  _spoolss_DeleteMonitor
10181 ****************************************************************/
10182
10183 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10184                               struct spoolss_DeleteMonitor *r)
10185 {
10186         p->rng_fault_state = true;
10187         return WERR_NOT_SUPPORTED;
10188 }
10189
10190 /****************************************************************
10191  _spoolss_DeletePrintProcessor
10192 ****************************************************************/
10193
10194 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10195                                      struct spoolss_DeletePrintProcessor *r)
10196 {
10197         p->rng_fault_state = true;
10198         return WERR_NOT_SUPPORTED;
10199 }
10200
10201 /****************************************************************
10202  _spoolss_AddPrintProvidor
10203 ****************************************************************/
10204
10205 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10206                                  struct spoolss_AddPrintProvidor *r)
10207 {
10208         p->rng_fault_state = true;
10209         return WERR_NOT_SUPPORTED;
10210 }
10211
10212 /****************************************************************
10213  _spoolss_DeletePrintProvidor
10214 ****************************************************************/
10215
10216 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10217                                     struct spoolss_DeletePrintProvidor *r)
10218 {
10219         p->rng_fault_state = true;
10220         return WERR_NOT_SUPPORTED;
10221 }
10222
10223 /****************************************************************
10224  _spoolss_FindFirstPrinterChangeNotification
10225 ****************************************************************/
10226
10227 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10228                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
10229 {
10230         p->rng_fault_state = true;
10231         return WERR_NOT_SUPPORTED;
10232 }
10233
10234 /****************************************************************
10235  _spoolss_FindNextPrinterChangeNotification
10236 ****************************************************************/
10237
10238 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10239                                                   struct spoolss_FindNextPrinterChangeNotification *r)
10240 {
10241         p->rng_fault_state = true;
10242         return WERR_NOT_SUPPORTED;
10243 }
10244
10245 /****************************************************************
10246  _spoolss_RouterFindFirstPrinterChangeNotificationOld
10247 ****************************************************************/
10248
10249 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10250                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10251 {
10252         p->rng_fault_state = true;
10253         return WERR_NOT_SUPPORTED;
10254 }
10255
10256 /****************************************************************
10257  _spoolss_ReplyOpenPrinter
10258 ****************************************************************/
10259
10260 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10261                                  struct spoolss_ReplyOpenPrinter *r)
10262 {
10263         p->rng_fault_state = true;
10264         return WERR_NOT_SUPPORTED;
10265 }
10266
10267 /****************************************************************
10268  _spoolss_RouterReplyPrinter
10269 ****************************************************************/
10270
10271 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10272                                    struct spoolss_RouterReplyPrinter *r)
10273 {
10274         p->rng_fault_state = true;
10275         return WERR_NOT_SUPPORTED;
10276 }
10277
10278 /****************************************************************
10279  _spoolss_ReplyClosePrinter
10280 ****************************************************************/
10281
10282 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10283                                   struct spoolss_ReplyClosePrinter *r)
10284 {
10285         p->rng_fault_state = true;
10286         return WERR_NOT_SUPPORTED;
10287 }
10288
10289 /****************************************************************
10290  _spoolss_AddPortEx
10291 ****************************************************************/
10292
10293 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10294                           struct spoolss_AddPortEx *r)
10295 {
10296         p->rng_fault_state = true;
10297         return WERR_NOT_SUPPORTED;
10298 }
10299
10300 /****************************************************************
10301  _spoolss_RouterFindFirstPrinterChangeNotification
10302 ****************************************************************/
10303
10304 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10305                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10306 {
10307         p->rng_fault_state = true;
10308         return WERR_NOT_SUPPORTED;
10309 }
10310
10311 /****************************************************************
10312  _spoolss_SpoolerInit
10313 ****************************************************************/
10314
10315 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10316                             struct spoolss_SpoolerInit *r)
10317 {
10318         p->rng_fault_state = true;
10319         return WERR_NOT_SUPPORTED;
10320 }
10321
10322 /****************************************************************
10323  _spoolss_ResetPrinterEx
10324 ****************************************************************/
10325
10326 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10327                                struct spoolss_ResetPrinterEx *r)
10328 {
10329         p->rng_fault_state = true;
10330         return WERR_NOT_SUPPORTED;
10331 }
10332
10333 /****************************************************************
10334  _spoolss_RouterReplyPrinterEx
10335 ****************************************************************/
10336
10337 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10338                                      struct spoolss_RouterReplyPrinterEx *r)
10339 {
10340         p->rng_fault_state = true;
10341         return WERR_NOT_SUPPORTED;
10342 }
10343
10344 /****************************************************************
10345  _spoolss_44
10346 ****************************************************************/
10347
10348 WERROR _spoolss_44(struct pipes_struct *p,
10349                    struct spoolss_44 *r)
10350 {
10351         p->rng_fault_state = true;
10352         return WERR_NOT_SUPPORTED;
10353 }
10354
10355 /****************************************************************
10356  _spoolss_SetPort
10357 ****************************************************************/
10358
10359 WERROR _spoolss_SetPort(struct pipes_struct *p,
10360                         struct spoolss_SetPort *r)
10361 {
10362         p->rng_fault_state = true;
10363         return WERR_NOT_SUPPORTED;
10364 }
10365
10366 /****************************************************************
10367  _spoolss_4a
10368 ****************************************************************/
10369
10370 WERROR _spoolss_4a(struct pipes_struct *p,
10371                    struct spoolss_4a *r)
10372 {
10373         p->rng_fault_state = true;
10374         return WERR_NOT_SUPPORTED;
10375 }
10376
10377 /****************************************************************
10378  _spoolss_4b
10379 ****************************************************************/
10380
10381 WERROR _spoolss_4b(struct pipes_struct *p,
10382                    struct spoolss_4b *r)
10383 {
10384         p->rng_fault_state = true;
10385         return WERR_NOT_SUPPORTED;
10386 }
10387
10388 /****************************************************************
10389  _spoolss_4c
10390 ****************************************************************/
10391
10392 WERROR _spoolss_4c(struct pipes_struct *p,
10393                    struct spoolss_4c *r)
10394 {
10395         p->rng_fault_state = true;
10396         return WERR_NOT_SUPPORTED;
10397 }
10398
10399 /****************************************************************
10400  _spoolss_53
10401 ****************************************************************/
10402
10403 WERROR _spoolss_53(struct pipes_struct *p,
10404                    struct spoolss_53 *r)
10405 {
10406         p->rng_fault_state = true;
10407         return WERR_NOT_SUPPORTED;
10408 }
10409
10410 /****************************************************************
10411  _spoolss_AddPerMachineConnection
10412 ****************************************************************/
10413
10414 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
10415                                         struct spoolss_AddPerMachineConnection *r)
10416 {
10417         p->rng_fault_state = true;
10418         return WERR_NOT_SUPPORTED;
10419 }
10420
10421 /****************************************************************
10422  _spoolss_DeletePerMachineConnection
10423 ****************************************************************/
10424
10425 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
10426                                            struct spoolss_DeletePerMachineConnection *r)
10427 {
10428         p->rng_fault_state = true;
10429         return WERR_NOT_SUPPORTED;
10430 }
10431
10432 /****************************************************************
10433  _spoolss_EnumPerMachineConnections
10434 ****************************************************************/
10435
10436 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
10437                                           struct spoolss_EnumPerMachineConnections *r)
10438 {
10439         p->rng_fault_state = true;
10440         return WERR_NOT_SUPPORTED;
10441 }
10442
10443 /****************************************************************
10444  _spoolss_5a
10445 ****************************************************************/
10446
10447 WERROR _spoolss_5a(struct pipes_struct *p,
10448                    struct spoolss_5a *r)
10449 {
10450         p->rng_fault_state = true;
10451         return WERR_NOT_SUPPORTED;
10452 }
10453
10454 /****************************************************************
10455  _spoolss_5b
10456 ****************************************************************/
10457
10458 WERROR _spoolss_5b(struct pipes_struct *p,
10459                    struct spoolss_5b *r)
10460 {
10461         p->rng_fault_state = true;
10462         return WERR_NOT_SUPPORTED;
10463 }
10464
10465 /****************************************************************
10466  _spoolss_5c
10467 ****************************************************************/
10468
10469 WERROR _spoolss_5c(struct pipes_struct *p,
10470                    struct spoolss_5c *r)
10471 {
10472         p->rng_fault_state = true;
10473         return WERR_NOT_SUPPORTED;
10474 }
10475
10476 /****************************************************************
10477  _spoolss_5d
10478 ****************************************************************/
10479
10480 WERROR _spoolss_5d(struct pipes_struct *p,
10481                    struct spoolss_5d *r)
10482 {
10483         p->rng_fault_state = true;
10484         return WERR_NOT_SUPPORTED;
10485 }
10486
10487 /****************************************************************
10488  _spoolss_5e
10489 ****************************************************************/
10490
10491 WERROR _spoolss_5e(struct pipes_struct *p,
10492                    struct spoolss_5e *r)
10493 {
10494         p->rng_fault_state = true;
10495         return WERR_NOT_SUPPORTED;
10496 }
10497
10498 /****************************************************************
10499  _spoolss_5f
10500 ****************************************************************/
10501
10502 WERROR _spoolss_5f(struct pipes_struct *p,
10503                    struct spoolss_5f *r)
10504 {
10505         p->rng_fault_state = true;
10506         return WERR_NOT_SUPPORTED;
10507 }
10508
10509 /****************************************************************
10510  _spoolss_60
10511 ****************************************************************/
10512
10513 WERROR _spoolss_60(struct pipes_struct *p,
10514                    struct spoolss_60 *r)
10515 {
10516         p->rng_fault_state = true;
10517         return WERR_NOT_SUPPORTED;
10518 }
10519
10520 /****************************************************************
10521  _spoolss_61
10522 ****************************************************************/
10523
10524 WERROR _spoolss_61(struct pipes_struct *p,
10525                    struct spoolss_61 *r)
10526 {
10527         p->rng_fault_state = true;
10528         return WERR_NOT_SUPPORTED;
10529 }
10530
10531 /****************************************************************
10532  _spoolss_62
10533 ****************************************************************/
10534
10535 WERROR _spoolss_62(struct pipes_struct *p,
10536                    struct spoolss_62 *r)
10537 {
10538         p->rng_fault_state = true;
10539         return WERR_NOT_SUPPORTED;
10540 }
10541
10542 /****************************************************************
10543  _spoolss_63
10544 ****************************************************************/
10545
10546 WERROR _spoolss_63(struct pipes_struct *p,
10547                    struct spoolss_63 *r)
10548 {
10549         p->rng_fault_state = true;
10550         return WERR_NOT_SUPPORTED;
10551 }
10552
10553 /****************************************************************
10554  _spoolss_64
10555 ****************************************************************/
10556
10557 WERROR _spoolss_64(struct pipes_struct *p,
10558                    struct spoolss_64 *r)
10559 {
10560         p->rng_fault_state = true;
10561         return WERR_NOT_SUPPORTED;
10562 }
10563
10564 /****************************************************************
10565  _spoolss_65
10566 ****************************************************************/
10567
10568 WERROR _spoolss_65(struct pipes_struct *p,
10569                    struct spoolss_65 *r)
10570 {
10571         p->rng_fault_state = true;
10572         return WERR_NOT_SUPPORTED;
10573 }
10574
10575 /****************************************************************
10576  _spoolss_GetCorePrinterDrivers
10577 ****************************************************************/
10578
10579 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
10580                                       struct spoolss_GetCorePrinterDrivers *r)
10581 {
10582         p->rng_fault_state = true;
10583         return WERR_NOT_SUPPORTED;
10584 }
10585
10586 /****************************************************************
10587  _spoolss_67
10588 ****************************************************************/
10589
10590 WERROR _spoolss_67(struct pipes_struct *p,
10591                    struct spoolss_67 *r)
10592 {
10593         p->rng_fault_state = true;
10594         return WERR_NOT_SUPPORTED;
10595 }
10596
10597 /****************************************************************
10598  _spoolss_GetPrinterDriverPackagePath
10599 ****************************************************************/
10600
10601 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
10602                                             struct spoolss_GetPrinterDriverPackagePath *r)
10603 {
10604         p->rng_fault_state = true;
10605         return WERR_NOT_SUPPORTED;
10606 }
10607
10608 /****************************************************************
10609  _spoolss_69
10610 ****************************************************************/
10611
10612 WERROR _spoolss_69(struct pipes_struct *p,
10613                    struct spoolss_69 *r)
10614 {
10615         p->rng_fault_state = true;
10616         return WERR_NOT_SUPPORTED;
10617 }
10618
10619 /****************************************************************
10620  _spoolss_6a
10621 ****************************************************************/
10622
10623 WERROR _spoolss_6a(struct pipes_struct *p,
10624                    struct spoolss_6a *r)
10625 {
10626         p->rng_fault_state = true;
10627         return WERR_NOT_SUPPORTED;
10628 }
10629
10630 /****************************************************************
10631  _spoolss_6b
10632 ****************************************************************/
10633
10634 WERROR _spoolss_6b(struct pipes_struct *p,
10635                    struct spoolss_6b *r)
10636 {
10637         p->rng_fault_state = true;
10638         return WERR_NOT_SUPPORTED;
10639 }
10640
10641 /****************************************************************
10642  _spoolss_6c
10643 ****************************************************************/
10644
10645 WERROR _spoolss_6c(struct pipes_struct *p,
10646                    struct spoolss_6c *r)
10647 {
10648         p->rng_fault_state = true;
10649         return WERR_NOT_SUPPORTED;
10650 }
10651
10652 /****************************************************************
10653  _spoolss_6d
10654 ****************************************************************/
10655
10656 WERROR _spoolss_6d(struct pipes_struct *p,
10657                    struct spoolss_6d *r)
10658 {
10659         p->rng_fault_state = true;
10660         return WERR_NOT_SUPPORTED;
10661 }