s3: Fix Coverity ID 1017, CHECKED_RETURN
[metze/samba/wip.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         if (!get_printer_snum(p, hnd, &snum, NULL)) {
3651                 return WERR_BADFID;
3652         }
3653
3654         /* Maybe we should use the SYSTEM session_info here... */
3655         result = winreg_get_printer(mem_ctx,
3656                                     get_session_info_system(),
3657                                     p->msg_ctx,
3658                                     lp_servicename(snum), &pinfo2);
3659         if (!W_ERROR_IS_OK(result)) {
3660                 return WERR_BADFID;
3661         }
3662
3663         for (i=0; i<option->count; i++) {
3664                 option_type = option->types[i];
3665
3666                 switch (option_type.type) {
3667                 case PRINTER_NOTIFY_TYPE:
3668                         if (construct_notify_printer_info(p->msg_ctx,
3669                                                           Printer, info,
3670                                                           pinfo2, snum,
3671                                                           &option_type, id,
3672                                                           mem_ctx)) {
3673                                 id--;
3674                         }
3675                         break;
3676
3677                 case JOB_NOTIFY_TYPE:
3678
3679                         count = print_queue_status(p->msg_ctx, snum, &queue,
3680                                                    &status);
3681
3682                         for (j=0; j<count; j++) {
3683                                 construct_notify_jobs_info(p->msg_ctx,
3684                                                            &queue[j], info,
3685                                                            pinfo2, snum,
3686                                                            &option_type,
3687                                                            queue[j].job,
3688                                                            mem_ctx);
3689                         }
3690
3691                         SAFE_FREE(queue);
3692                         break;
3693                 }
3694         }
3695
3696         /*
3697          * Debugging information, don't delete.
3698          */
3699         /*
3700         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3701         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3702         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3703
3704         for (i=0; i<info->count; i++) {
3705                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3706                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3707                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3708         }
3709         */
3710
3711         talloc_free(pinfo2);
3712         return WERR_OK;
3713 }
3714
3715 /****************************************************************
3716  _spoolss_RouterRefreshPrinterChangeNotify
3717 ****************************************************************/
3718
3719 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3720                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3721 {
3722         struct spoolss_NotifyInfo *info;
3723
3724         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3725         WERROR result = WERR_BADFID;
3726
3727         /* we always have a spoolss_NotifyInfo struct */
3728         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3729         if (!info) {
3730                 result = WERR_NOMEM;
3731                 goto done;
3732         }
3733
3734         *r->out.info = info;
3735
3736         if (!Printer) {
3737                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3738                         "Invalid handle (%s:%u:%u).\n",
3739                         OUR_HANDLE(r->in.handle)));
3740                 goto done;
3741         }
3742
3743         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3744
3745         /*
3746          *      We are now using the change value, and
3747          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3748          *      I don't have a global notification system, I'm sending back all the
3749          *      information even when _NOTHING_ has changed.
3750          */
3751
3752         /* We need to keep track of the change value to send back in
3753            RRPCN replies otherwise our updates are ignored. */
3754
3755         Printer->notify.fnpcn = true;
3756
3757         if (Printer->notify.cli_chan != NULL &&
3758             Printer->notify.cli_chan->active_connections > 0) {
3759                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3760                         "Saving change value in request [%x]\n",
3761                         r->in.change_low));
3762                 Printer->notify.change = r->in.change_low;
3763         }
3764
3765         /* just ignore the spoolss_NotifyOption */
3766
3767         switch (Printer->printer_type) {
3768                 case SPLHND_SERVER:
3769                         result = printserver_notify_info(p, r->in.handle,
3770                                                          info, p->mem_ctx);
3771                         break;
3772
3773                 case SPLHND_PRINTER:
3774                         result = printer_notify_info(p, r->in.handle,
3775                                                      info, p->mem_ctx);
3776                         break;
3777         }
3778
3779         Printer->notify.fnpcn = false;
3780
3781 done:
3782         return result;
3783 }
3784
3785 /********************************************************************
3786  ********************************************************************/
3787
3788 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3789                                  const char *servername,
3790                                  const char *printername,
3791                                  const char **printername_p)
3792 {
3793         /* FIXME: add lp_force_printername() */
3794
3795         if (servername == NULL) {
3796                 *printername_p = talloc_strdup(mem_ctx, printername);
3797                 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3798                 return WERR_OK;
3799         }
3800
3801         if (servername[0] == '\\' && servername[1] == '\\') {
3802                 servername += 2;
3803         }
3804
3805         *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3806         W_ERROR_HAVE_NO_MEMORY(*printername_p);
3807
3808         return WERR_OK;
3809 }
3810
3811 /********************************************************************
3812  ********************************************************************/
3813
3814 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3815                                           const char *printername)
3816 {
3817         if (dm == NULL) {
3818                 return;
3819         }
3820
3821         dm->devicename = talloc_strndup(dm, printername,
3822                                         MIN(strlen(printername), 31));
3823 }
3824
3825 /********************************************************************
3826  * construct_printer_info_0
3827  * fill a printer_info_0 struct
3828  ********************************************************************/
3829
3830 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3831                                       const struct auth_serversupplied_info *session_info,
3832                                       struct messaging_context *msg_ctx,
3833                                       struct spoolss_PrinterInfo2 *info2,
3834                                       const char *servername,
3835                                       struct spoolss_PrinterInfo0 *r,
3836                                       int snum)
3837 {
3838         int count;
3839         struct printer_session_counter *session_counter;
3840         struct timeval setuptime;
3841         print_status_struct status;
3842         WERROR result;
3843
3844         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3845         if (!W_ERROR_IS_OK(result)) {
3846                 return result;
3847         }
3848
3849         if (servername) {
3850                 r->servername = talloc_strdup(mem_ctx, servername);
3851                 W_ERROR_HAVE_NO_MEMORY(r->servername);
3852         } else {
3853                 r->servername = NULL;
3854         }
3855
3856         count = print_queue_length(msg_ctx, snum, &status);
3857
3858         /* check if we already have a counter for this printer */
3859         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3860                 if (session_counter->snum == snum)
3861                         break;
3862         }
3863
3864         /* it's the first time, add it to the list */
3865         if (session_counter == NULL) {
3866                 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3867                 W_ERROR_HAVE_NO_MEMORY(session_counter);
3868                 session_counter->snum           = snum;
3869                 session_counter->counter        = 0;
3870                 DLIST_ADD(counter_list, session_counter);
3871         }
3872
3873         /* increment it */
3874         session_counter->counter++;
3875
3876         r->cjobs                        = count;
3877         r->total_jobs                   = 0;
3878         r->total_bytes                  = 0;
3879
3880         get_startup_time(&setuptime);
3881         init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3882
3883         /* JFM:
3884          * the global_counter should be stored in a TDB as it's common to all the clients
3885          * and should be zeroed on samba startup
3886          */
3887         r->global_counter               = session_counter->counter;
3888         r->total_pages                  = 0;
3889         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3890         SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3891         SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3892         r->free_build                   = SPOOLSS_RELEASE_BUILD;
3893         r->spooling                     = 0;
3894         r->max_spooling                 = 0;
3895         r->session_counter              = session_counter->counter;
3896         r->num_error_out_of_paper       = 0x0;
3897         r->num_error_not_ready          = 0x0;          /* number of print failure */
3898         r->job_error                    = 0x0;
3899         r->number_of_processors         = 0x1;
3900         r->processor_type               = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3901         r->high_part_total_bytes        = 0x0;
3902
3903         /* ChangeID in milliseconds*/
3904         winreg_printer_get_changeid(mem_ctx, session_info, msg_ctx,
3905                                     info2->sharename, &r->change_id);
3906
3907         r->last_error                   = WERR_OK;
3908         r->status                       = nt_printq_status(status.status);
3909         r->enumerate_network_printers   = 0x0;
3910         r->c_setprinter                 = 0x0;
3911         r->processor_architecture       = PROCESSOR_ARCHITECTURE_INTEL;
3912         r->processor_level              = 0x6;          /* 6  ???*/
3913         r->ref_ic                       = 0;
3914         r->reserved2                    = 0;
3915         r->reserved3                    = 0;
3916
3917         return WERR_OK;
3918 }
3919
3920
3921 /********************************************************************
3922  * construct_printer_info1
3923  * fill a spoolss_PrinterInfo1 struct
3924 ********************************************************************/
3925
3926 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3927                                       const struct spoolss_PrinterInfo2 *info2,
3928                                       uint32_t flags,
3929                                       const char *servername,
3930                                       struct spoolss_PrinterInfo1 *r,
3931                                       int snum)
3932 {
3933         WERROR result;
3934
3935         r->flags                = flags;
3936
3937         if (info2->comment == NULL || info2->comment[0] == '\0') {
3938                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
3939         } else {
3940                 r->comment      = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3941         }
3942         W_ERROR_HAVE_NO_MEMORY(r->comment);
3943
3944         result = create_printername(mem_ctx, servername, info2->printername, &r->name);
3945         if (!W_ERROR_IS_OK(result)) {
3946                 return result;
3947         }
3948
3949         r->description          = talloc_asprintf(mem_ctx, "%s,%s,%s",
3950                                                   r->name,
3951                                                   info2->drivername,
3952                                                   r->comment);
3953         W_ERROR_HAVE_NO_MEMORY(r->description);
3954
3955         return WERR_OK;
3956 }
3957
3958 /********************************************************************
3959  * construct_printer_info2
3960  * fill a spoolss_PrinterInfo2 struct
3961 ********************************************************************/
3962
3963 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3964                                       struct messaging_context *msg_ctx,
3965                                       const struct spoolss_PrinterInfo2 *info2,
3966                                       const char *servername,
3967                                       struct spoolss_PrinterInfo2 *r,
3968                                       int snum)
3969 {
3970         int count;
3971         print_status_struct status;
3972         WERROR result;
3973
3974         count = print_queue_length(msg_ctx, snum, &status);
3975
3976         if (servername) {
3977                 r->servername           = talloc_strdup(mem_ctx, servername);
3978                 W_ERROR_HAVE_NO_MEMORY(r->servername);
3979         } else {
3980                 r->servername           = NULL;
3981         }
3982
3983         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3984         if (!W_ERROR_IS_OK(result)) {
3985                 return result;
3986         }
3987
3988         r->sharename            = talloc_strdup(mem_ctx, lp_servicename(snum));
3989         W_ERROR_HAVE_NO_MEMORY(r->sharename);
3990         r->portname             = talloc_strdup(mem_ctx, info2->portname);
3991         W_ERROR_HAVE_NO_MEMORY(r->portname);
3992         r->drivername           = talloc_strdup(mem_ctx, info2->drivername);
3993         W_ERROR_HAVE_NO_MEMORY(r->drivername);
3994
3995         if (info2->comment[0] == '\0') {
3996                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
3997         } else {
3998                 r->comment      = talloc_strdup(mem_ctx, info2->comment);
3999         }
4000         W_ERROR_HAVE_NO_MEMORY(r->comment);
4001
4002         r->location             = talloc_strdup(mem_ctx, info2->location);
4003         W_ERROR_HAVE_NO_MEMORY(r->location);
4004         r->sepfile              = talloc_strdup(mem_ctx, info2->sepfile);
4005         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4006         r->printprocessor       = talloc_strdup(mem_ctx, info2->printprocessor);
4007         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4008         r->datatype             = talloc_strdup(mem_ctx, info2->datatype);
4009         W_ERROR_HAVE_NO_MEMORY(r->datatype);
4010         r->parameters           = talloc_strdup(mem_ctx, info2->parameters);
4011         W_ERROR_HAVE_NO_MEMORY(r->parameters);
4012
4013         r->attributes           = info2->attributes;
4014
4015         r->priority             = info2->priority;
4016         r->defaultpriority      = info2->defaultpriority;
4017         r->starttime            = info2->starttime;
4018         r->untiltime            = info2->untiltime;
4019         r->status               = nt_printq_status(status.status);
4020         r->cjobs                = count;
4021         r->averageppm           = info2->averageppm;
4022
4023         copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4024         if (!r->devmode) {
4025                 DEBUG(8,("Returning NULL Devicemode!\n"));
4026         }
4027
4028         compose_devicemode_devicename(r->devmode, r->printername);
4029
4030         r->secdesc = NULL;
4031
4032         if (info2->secdesc != NULL) {
4033                 /* don't use talloc_steal() here unless you do a deep steal of all
4034                    the SEC_DESC members */
4035
4036                 r->secdesc      = dup_sec_desc(mem_ctx, info2->secdesc);
4037         }
4038
4039         return WERR_OK;
4040 }
4041
4042 /********************************************************************
4043  * construct_printer_info3
4044  * fill a spoolss_PrinterInfo3 struct
4045  ********************************************************************/
4046
4047 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4048                                       const struct spoolss_PrinterInfo2 *info2,
4049                                       const char *servername,
4050                                       struct spoolss_PrinterInfo3 *r,
4051                                       int snum)
4052 {
4053         /* These are the components of the SD we are returning. */
4054
4055         if (info2->secdesc != NULL) {
4056                 /* don't use talloc_steal() here unless you do a deep steal of all
4057                    the SEC_DESC members */
4058
4059                 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4060                 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
4061         }
4062
4063         return WERR_OK;
4064 }
4065
4066 /********************************************************************
4067  * construct_printer_info4
4068  * fill a spoolss_PrinterInfo4 struct
4069  ********************************************************************/
4070
4071 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4072                                       const struct spoolss_PrinterInfo2 *info2,
4073                                       const char *servername,
4074                                       struct spoolss_PrinterInfo4 *r,
4075                                       int snum)
4076 {
4077         WERROR result;
4078
4079         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4080         if (!W_ERROR_IS_OK(result)) {
4081                 return result;
4082         }
4083
4084         if (servername) {
4085                 r->servername   = talloc_strdup(mem_ctx, servername);
4086                 W_ERROR_HAVE_NO_MEMORY(r->servername);
4087         } else {
4088                 r->servername = NULL;
4089         }
4090
4091         r->attributes   = info2->attributes;
4092
4093         return WERR_OK;
4094 }
4095
4096 /********************************************************************
4097  * construct_printer_info5
4098  * fill a spoolss_PrinterInfo5 struct
4099  ********************************************************************/
4100
4101 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4102                                       const struct spoolss_PrinterInfo2 *info2,
4103                                       const char *servername,
4104                                       struct spoolss_PrinterInfo5 *r,
4105                                       int snum)
4106 {
4107         WERROR result;
4108
4109         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4110         if (!W_ERROR_IS_OK(result)) {
4111                 return result;
4112         }
4113
4114         r->portname     = talloc_strdup(mem_ctx, info2->portname);
4115         W_ERROR_HAVE_NO_MEMORY(r->portname);
4116
4117         r->attributes   = info2->attributes;
4118
4119         /* these two are not used by NT+ according to MSDN */
4120         r->device_not_selected_timeout          = 0x0;  /* have seen 0x3a98 */
4121         r->transmission_retry_timeout           = 0x0;  /* have seen 0xafc8 */
4122
4123         return WERR_OK;
4124 }
4125
4126 /********************************************************************
4127  * construct_printer_info_6
4128  * fill a spoolss_PrinterInfo6 struct
4129  ********************************************************************/
4130
4131 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4132                                       struct messaging_context *msg_ctx,
4133                                       const struct spoolss_PrinterInfo2 *info2,
4134                                       const char *servername,
4135                                       struct spoolss_PrinterInfo6 *r,
4136                                       int snum)
4137 {
4138         int count;
4139         print_status_struct status;
4140
4141         count = print_queue_length(msg_ctx, snum, &status);
4142
4143         r->status = nt_printq_status(status.status);
4144
4145         return WERR_OK;
4146 }
4147
4148 /********************************************************************
4149  * construct_printer_info7
4150  * fill a spoolss_PrinterInfo7 struct
4151  ********************************************************************/
4152
4153 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4154                                       struct messaging_context *msg_ctx,
4155                                       const char *servername,
4156                                       struct spoolss_PrinterInfo7 *r,
4157                                       int snum)
4158 {
4159         struct auth_serversupplied_info *session_info;
4160         struct GUID guid;
4161         NTSTATUS status;
4162
4163         status = make_session_info_system(mem_ctx, &session_info);
4164         if (!NT_STATUS_IS_OK(status)) {
4165                 DEBUG(0, ("construct_printer_info7: "
4166                           "Could not create system session_info\n"));
4167                 return WERR_NOMEM;
4168         }
4169
4170         if (is_printer_published(mem_ctx, session_info, msg_ctx,
4171                                  servername,
4172                                  lp_servicename(snum), &guid, NULL)) {
4173                 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4174                 r->action = DSPRINT_PUBLISH;
4175         } else {
4176                 r->guid = talloc_strdup(mem_ctx, "");
4177                 r->action = DSPRINT_UNPUBLISH;
4178         }
4179         W_ERROR_HAVE_NO_MEMORY(r->guid);
4180
4181         TALLOC_FREE(session_info);
4182         return WERR_OK;
4183 }
4184
4185 /********************************************************************
4186  * construct_printer_info8
4187  * fill a spoolss_PrinterInfo8 struct
4188  ********************************************************************/
4189
4190 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4191                                       const struct spoolss_PrinterInfo2 *info2,
4192                                       const char *servername,
4193                                       struct spoolss_DeviceModeInfo *r,
4194                                       int snum)
4195 {
4196         WERROR result;
4197         const char *printername;
4198
4199         result = create_printername(mem_ctx, servername, info2->printername, &printername);
4200         if (!W_ERROR_IS_OK(result)) {
4201                 return result;
4202         }
4203
4204         copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4205         if (!r->devmode) {
4206                 DEBUG(8,("Returning NULL Devicemode!\n"));
4207         }
4208
4209         compose_devicemode_devicename(r->devmode, printername);
4210
4211         return WERR_OK;
4212 }
4213
4214
4215 /********************************************************************
4216 ********************************************************************/
4217
4218 static bool snum_is_shared_printer(int snum)
4219 {
4220         return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4221 }
4222
4223 /********************************************************************
4224  Spoolss_enumprinters.
4225 ********************************************************************/
4226
4227 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4228                                            const struct auth_serversupplied_info *session_info,
4229                                            struct messaging_context *msg_ctx,
4230                                            const char *servername,
4231                                            uint32_t level,
4232                                            uint32_t flags,
4233                                            union spoolss_PrinterInfo **info_p,
4234                                            uint32_t *count_p)
4235 {
4236         int snum;
4237         int n_services = lp_numservices();
4238         union spoolss_PrinterInfo *info = NULL;
4239         uint32_t count = 0;
4240         WERROR result = WERR_OK;
4241
4242         *count_p = 0;
4243         *info_p = NULL;
4244
4245         for (snum = 0; snum < n_services; snum++) {
4246
4247                 const char *printer;
4248                 struct spoolss_PrinterInfo2 *info2;
4249
4250                 if (!snum_is_shared_printer(snum)) {
4251                         continue;
4252                 }
4253
4254                 printer = lp_const_servicename(snum);
4255
4256                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4257                         printer, snum));
4258
4259                 result = winreg_create_printer(mem_ctx,
4260                                                session_info,
4261                                                msg_ctx,
4262                                                printer);
4263                 if (!W_ERROR_IS_OK(result)) {
4264                         goto out;
4265                 }
4266
4267                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
4268                                             union spoolss_PrinterInfo,
4269                                             count + 1);
4270                 if (!info) {
4271                         result = WERR_NOMEM;
4272                         goto out;
4273                 }
4274
4275                 result = winreg_get_printer(mem_ctx, session_info, msg_ctx,
4276                                             printer, &info2);
4277                 if (!W_ERROR_IS_OK(result)) {
4278                         goto out;
4279                 }
4280
4281                 switch (level) {
4282                 case 0:
4283                         result = construct_printer_info0(info, session_info,
4284                                                          msg_ctx, info2,
4285                                                          servername,
4286                                                          &info[count].info0, snum);
4287                         break;
4288                 case 1:
4289                         result = construct_printer_info1(info, info2, flags,
4290                                                          servername,
4291                                                          &info[count].info1, snum);
4292                         break;
4293                 case 2:
4294                         result = construct_printer_info2(info, msg_ctx, info2,
4295                                                          servername,
4296                                                          &info[count].info2, snum);
4297                         break;
4298                 case 4:
4299                         result = construct_printer_info4(info, info2,
4300                                                          servername,
4301                                                          &info[count].info4, snum);
4302                         break;
4303                 case 5:
4304                         result = construct_printer_info5(info, info2,
4305                                                          servername,
4306                                                          &info[count].info5, snum);
4307                         break;
4308
4309                 default:
4310                         result = WERR_UNKNOWN_LEVEL;
4311                         goto out;
4312                 }
4313
4314                 if (!W_ERROR_IS_OK(result)) {
4315                         goto out;
4316                 }
4317
4318                 count++;
4319         }
4320
4321         *count_p = count;
4322         *info_p = info;
4323
4324  out:
4325         if (!W_ERROR_IS_OK(result)) {
4326                 TALLOC_FREE(info);
4327                 return result;
4328         }
4329
4330         *info_p = info;
4331
4332         return WERR_OK;
4333 }
4334
4335 /********************************************************************
4336  * handle enumeration of printers at level 0
4337  ********************************************************************/
4338
4339 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4340                                   const struct auth_serversupplied_info *session_info,
4341                                   struct messaging_context *msg_ctx,
4342                                   uint32_t flags,
4343                                   const char *servername,
4344                                   union spoolss_PrinterInfo **info,
4345                                   uint32_t *count)
4346 {
4347         DEBUG(4,("enum_all_printers_info_0\n"));
4348
4349         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4350                                             servername, 0, flags, info, count);
4351 }
4352
4353
4354 /********************************************************************
4355 ********************************************************************/
4356
4357 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4358                                        const struct auth_serversupplied_info *session_info,
4359                                        struct messaging_context *msg_ctx,
4360                                        const char *servername,
4361                                        uint32_t flags,
4362                                        union spoolss_PrinterInfo **info,
4363                                        uint32_t *count)
4364 {
4365         DEBUG(4,("enum_all_printers_info_1\n"));
4366
4367         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4368                                             servername, 1, flags, info, count);
4369 }
4370
4371 /********************************************************************
4372  enum_all_printers_info_1_local.
4373 *********************************************************************/
4374
4375 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4376                                              const struct auth_serversupplied_info *session_info,
4377                                              struct messaging_context *msg_ctx,
4378                                              const char *servername,
4379                                              union spoolss_PrinterInfo **info,
4380                                              uint32_t *count)
4381 {
4382         DEBUG(4,("enum_all_printers_info_1_local\n"));
4383
4384         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4385                                         servername, PRINTER_ENUM_ICON8, info, count);
4386 }
4387
4388 /********************************************************************
4389  enum_all_printers_info_1_name.
4390 *********************************************************************/
4391
4392 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4393                                             const struct auth_serversupplied_info *session_info,
4394                                             struct messaging_context *msg_ctx,
4395                                             const char *servername,
4396                                             union spoolss_PrinterInfo **info,
4397                                             uint32_t *count)
4398 {
4399         const char *s = servername;
4400
4401         DEBUG(4,("enum_all_printers_info_1_name\n"));
4402
4403         if ((servername[0] == '\\') && (servername[1] == '\\')) {
4404                 s = servername + 2;
4405         }
4406
4407         if (!is_myname_or_ipaddr(s)) {
4408                 return WERR_INVALID_NAME;
4409         }
4410
4411         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4412                                         servername, PRINTER_ENUM_ICON8, info, count);
4413 }
4414
4415 /********************************************************************
4416  enum_all_printers_info_1_network.
4417 *********************************************************************/
4418
4419 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4420                                                const struct auth_serversupplied_info *session_info,
4421                                                struct messaging_context *msg_ctx,
4422                                                const char *servername,
4423                                                union spoolss_PrinterInfo **info,
4424                                                uint32_t *count)
4425 {
4426         const char *s = servername;
4427
4428         DEBUG(4,("enum_all_printers_info_1_network\n"));
4429
4430         /* If we respond to a enum_printers level 1 on our name with flags
4431            set to PRINTER_ENUM_REMOTE with a list of printers then these
4432            printers incorrectly appear in the APW browse list.
4433            Specifically the printers for the server appear at the workgroup
4434            level where all the other servers in the domain are
4435            listed. Windows responds to this call with a
4436            WERR_CAN_NOT_COMPLETE so we should do the same. */
4437
4438         if (servername[0] == '\\' && servername[1] == '\\') {
4439                  s = servername + 2;
4440         }
4441
4442         if (is_myname_or_ipaddr(s)) {
4443                  return WERR_CAN_NOT_COMPLETE;
4444         }
4445
4446         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4447                                         servername, PRINTER_ENUM_NAME, info, count);
4448 }
4449
4450 /********************************************************************
4451  * api_spoolss_enumprinters
4452  *
4453  * called from api_spoolss_enumprinters (see this to understand)
4454  ********************************************************************/
4455
4456 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4457                                        const struct auth_serversupplied_info *session_info,
4458                                        struct messaging_context *msg_ctx,
4459                                        const char *servername,
4460                                        union spoolss_PrinterInfo **info,
4461                                        uint32_t *count)
4462 {
4463         DEBUG(4,("enum_all_printers_info_2\n"));
4464
4465         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4466                                             servername, 2, 0, info, count);
4467 }
4468
4469 /********************************************************************
4470  * handle enumeration of printers at level 1
4471  ********************************************************************/
4472
4473 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4474                                   const struct auth_serversupplied_info *session_info,
4475                                   struct messaging_context *msg_ctx,
4476                                   uint32_t flags,
4477                                   const char *servername,
4478                                   union spoolss_PrinterInfo **info,
4479                                   uint32_t *count)
4480 {
4481         /* Not all the flags are equals */
4482
4483         if (flags & PRINTER_ENUM_LOCAL) {
4484                 return enum_all_printers_info_1_local(mem_ctx, session_info,
4485                                                       msg_ctx, servername, info, count);
4486         }
4487
4488         if (flags & PRINTER_ENUM_NAME) {
4489                 return enum_all_printers_info_1_name(mem_ctx, session_info,
4490                                                      msg_ctx, servername, info,
4491                                                      count);
4492         }
4493
4494         if (flags & PRINTER_ENUM_NETWORK) {
4495                 return enum_all_printers_info_1_network(mem_ctx, session_info,
4496                                                         msg_ctx, servername, info,
4497                                                         count);
4498         }
4499
4500         return WERR_OK; /* NT4sp5 does that */
4501 }
4502
4503 /********************************************************************
4504  * handle enumeration of printers at level 2
4505  ********************************************************************/
4506
4507 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4508                                   const struct auth_serversupplied_info *session_info,
4509                                   struct messaging_context *msg_ctx,
4510                                   uint32_t flags,
4511                                   const char *servername,
4512                                   union spoolss_PrinterInfo **info,
4513                                   uint32_t *count)
4514 {
4515         if (flags & PRINTER_ENUM_LOCAL) {
4516
4517                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4518                                                 servername,
4519                                                 info, count);
4520         }
4521
4522         if (flags & PRINTER_ENUM_NAME) {
4523                 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4524                         return WERR_INVALID_NAME;
4525                 }
4526
4527                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4528                                                 servername,
4529                                                 info, count);
4530         }
4531
4532         if (flags & PRINTER_ENUM_REMOTE) {
4533                 return WERR_UNKNOWN_LEVEL;
4534         }
4535
4536         return WERR_OK;
4537 }
4538
4539 /********************************************************************
4540  * handle enumeration of printers at level 4
4541  ********************************************************************/
4542
4543 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4544                                   const struct auth_serversupplied_info *session_info,
4545                                   struct messaging_context *msg_ctx,
4546                                   uint32_t flags,
4547                                   const char *servername,
4548                                   union spoolss_PrinterInfo **info,
4549                                   uint32_t *count)
4550 {
4551         DEBUG(4,("enum_all_printers_info_4\n"));
4552
4553         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4554                                             servername, 4, flags, info, count);
4555 }
4556
4557
4558 /********************************************************************
4559  * handle enumeration of printers at level 5
4560  ********************************************************************/
4561
4562 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4563                                   const struct auth_serversupplied_info *session_info,
4564                                   struct messaging_context *msg_ctx,
4565                                   uint32_t flags,
4566                                   const char *servername,
4567                                   union spoolss_PrinterInfo **info,
4568                                   uint32_t *count)
4569 {
4570         DEBUG(4,("enum_all_printers_info_5\n"));
4571
4572         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4573                                             servername, 5, flags, info, count);
4574 }
4575
4576 /****************************************************************
4577  _spoolss_EnumPrinters
4578 ****************************************************************/
4579
4580 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4581                              struct spoolss_EnumPrinters *r)
4582 {
4583         const struct auth_serversupplied_info *session_info = get_session_info_system();
4584         WERROR result;
4585
4586         /* that's an [in out] buffer */
4587
4588         if (!r->in.buffer && (r->in.offered != 0)) {
4589                 return WERR_INVALID_PARAM;
4590         }
4591
4592         DEBUG(4,("_spoolss_EnumPrinters\n"));
4593
4594         *r->out.needed = 0;
4595         *r->out.count = 0;
4596         *r->out.info = NULL;
4597
4598         /*
4599          * Level 1:
4600          *          flags==PRINTER_ENUM_NAME
4601          *           if name=="" then enumerates all printers
4602          *           if name!="" then enumerate the printer
4603          *          flags==PRINTER_ENUM_REMOTE
4604          *          name is NULL, enumerate printers
4605          * Level 2: name!="" enumerates printers, name can't be NULL
4606          * Level 3: doesn't exist
4607          * Level 4: does a local registry lookup
4608          * Level 5: same as Level 2
4609          */
4610
4611         if (r->in.server && r->in.server[0] == '\0') {
4612                 r->in.server = NULL;
4613         }
4614
4615         switch (r->in.level) {
4616         case 0:
4617                 result = enumprinters_level0(p->mem_ctx, session_info,
4618                                              p->msg_ctx, r->in.flags,
4619                                              r->in.server,
4620                                              r->out.info, r->out.count);
4621                 break;
4622         case 1:
4623                 result = enumprinters_level1(p->mem_ctx, session_info,
4624                                              p->msg_ctx, r->in.flags,
4625                                              r->in.server,
4626                                              r->out.info, r->out.count);
4627                 break;
4628         case 2:
4629                 result = enumprinters_level2(p->mem_ctx, session_info,
4630                                              p->msg_ctx, r->in.flags,
4631                                              r->in.server,
4632                                              r->out.info, r->out.count);
4633                 break;
4634         case 4:
4635                 result = enumprinters_level4(p->mem_ctx, session_info,
4636                                              p->msg_ctx, r->in.flags,
4637                                              r->in.server,
4638                                              r->out.info, r->out.count);
4639                 break;
4640         case 5:
4641                 result = enumprinters_level5(p->mem_ctx, session_info,
4642                                              p->msg_ctx, r->in.flags,
4643                                              r->in.server,
4644                                              r->out.info, r->out.count);
4645                 break;
4646         default:
4647                 return WERR_UNKNOWN_LEVEL;
4648         }
4649
4650         if (!W_ERROR_IS_OK(result)) {
4651                 return result;
4652         }
4653
4654         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4655                                                      spoolss_EnumPrinters,
4656                                                      *r->out.info, r->in.level,
4657                                                      *r->out.count);
4658         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4659         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4660
4661         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4662 }
4663
4664 /****************************************************************
4665  _spoolss_GetPrinter
4666 ****************************************************************/
4667
4668 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4669                            struct spoolss_GetPrinter *r)
4670 {
4671         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4672         struct spoolss_PrinterInfo2 *info2 = NULL;
4673         WERROR result = WERR_OK;
4674         int snum;
4675
4676         /* that's an [in out] buffer */
4677
4678         if (!r->in.buffer && (r->in.offered != 0)) {
4679                 return WERR_INVALID_PARAM;
4680         }
4681
4682         *r->out.needed = 0;
4683
4684         if (Printer == NULL) {
4685                 return WERR_BADFID;
4686         }
4687
4688         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4689                 return WERR_BADFID;
4690         }
4691
4692         result = winreg_get_printer(p->mem_ctx,
4693                                     get_session_info_system(),
4694                                     p->msg_ctx,
4695                                     lp_const_servicename(snum),
4696                                     &info2);
4697         if (!W_ERROR_IS_OK(result)) {
4698                 goto out;
4699         }
4700
4701         switch (r->in.level) {
4702         case 0:
4703                 result = construct_printer_info0(p->mem_ctx,
4704                                                  get_session_info_system(),
4705                                                  p->msg_ctx,
4706                                                  info2,
4707                                                  Printer->servername,
4708                                                  &r->out.info->info0,
4709                                                  snum);
4710                 break;
4711         case 1:
4712                 result = construct_printer_info1(p->mem_ctx, info2,
4713                                                  PRINTER_ENUM_ICON8,
4714                                                  Printer->servername,
4715                                                  &r->out.info->info1, snum);
4716                 break;
4717         case 2:
4718                 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4719                                                  Printer->servername,
4720                                                  &r->out.info->info2, snum);
4721                 break;
4722         case 3:
4723                 result = construct_printer_info3(p->mem_ctx, info2,
4724                                                  Printer->servername,
4725                                                  &r->out.info->info3, snum);
4726                 break;
4727         case 4:
4728                 result = construct_printer_info4(p->mem_ctx, info2,
4729                                                  Printer->servername,
4730                                                  &r->out.info->info4, snum);
4731                 break;
4732         case 5:
4733                 result = construct_printer_info5(p->mem_ctx, info2,
4734                                                  Printer->servername,
4735                                                  &r->out.info->info5, snum);
4736                 break;
4737         case 6:
4738                 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4739                                                  Printer->servername,
4740                                                  &r->out.info->info6, snum);
4741                 break;
4742         case 7:
4743                 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4744                                                  Printer->servername,
4745                                                  &r->out.info->info7, snum);
4746                 break;
4747         case 8:
4748                 result = construct_printer_info8(p->mem_ctx, info2,
4749                                                  Printer->servername,
4750                                                  &r->out.info->info8, snum);
4751                 break;
4752         default:
4753                 result = WERR_UNKNOWN_LEVEL;
4754                 break;
4755         }
4756
4757  out:
4758         if (!W_ERROR_IS_OK(result)) {
4759                 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4760                           r->in.level, win_errstr(result)));
4761                 TALLOC_FREE(r->out.info);
4762                 return result;
4763         }
4764
4765         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4766                                                r->out.info, r->in.level);
4767         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4768
4769         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4770 }
4771
4772 /********************************************************************
4773  ********************************************************************/
4774
4775 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4776         do { \
4777                 if (in && strlen(in)) { \
4778                         out = talloc_strdup(mem_ctx, in); \
4779                 } else { \
4780                         out = talloc_strdup(mem_ctx, ""); \
4781                 } \
4782                 W_ERROR_HAVE_NO_MEMORY(out); \
4783         } while (0);
4784
4785 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4786         do { \
4787                 if (in && strlen(in)) { \
4788                         out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4789                 } else { \
4790                         out = talloc_strdup(mem_ctx, ""); \
4791                 } \
4792                 W_ERROR_HAVE_NO_MEMORY(out); \
4793         } while (0);
4794
4795 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4796                                                   const char **string_array,
4797                                                   const char ***presult,
4798                                                   const char *cservername,
4799                                                   const char *arch,
4800                                                   int version)
4801 {
4802         int i, num_strings = 0;
4803         const char **array = NULL;
4804
4805         if (string_array == NULL) {
4806                 return WERR_INVALID_PARAMETER;
4807         }
4808
4809         for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4810                 const char *str = NULL;
4811
4812                 if (cservername == NULL || arch == NULL) {
4813                         FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4814                 } else {
4815                         FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4816                 }
4817
4818                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4819                         TALLOC_FREE(array);
4820                         return WERR_NOMEM;
4821                 }
4822         }
4823
4824         if (i > 0) {
4825                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4826                              &array, &num_strings);
4827         }
4828
4829         if (presult) {
4830                 *presult = array;
4831         }
4832
4833         return WERR_OK;
4834 }
4835
4836 /********************************************************************
4837  * fill a spoolss_DriverInfo1 struct
4838  ********************************************************************/
4839
4840 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4841                                         struct spoolss_DriverInfo1 *r,
4842                                         const struct spoolss_DriverInfo8 *driver,
4843                                         const char *servername)
4844 {
4845         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4846         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4847
4848         return WERR_OK;
4849 }
4850
4851 /********************************************************************
4852  * fill a spoolss_DriverInfo2 struct
4853  ********************************************************************/
4854
4855 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4856                                         struct spoolss_DriverInfo2 *r,
4857                                         const struct spoolss_DriverInfo8 *driver,
4858                                         const char *servername)
4859
4860 {
4861         const char *cservername = canon_servername(servername);
4862
4863         r->version              = driver->version;
4864
4865         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4866         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4867         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4868         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4869
4870         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4871                                driver->architecture,
4872                                driver->version,
4873                                driver->driver_path,
4874                                r->driver_path);
4875
4876         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4877                                driver->architecture,
4878                                driver->version,
4879                                driver->data_file,
4880                                r->data_file);
4881
4882         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4883                                driver->architecture,
4884                                driver->version,
4885                                driver->config_file,
4886                                r->config_file);
4887
4888         return WERR_OK;
4889 }
4890
4891 /********************************************************************
4892  * fill a spoolss_DriverInfo3 struct
4893  ********************************************************************/
4894
4895 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4896                                         struct spoolss_DriverInfo3 *r,
4897                                         const struct spoolss_DriverInfo8 *driver,
4898                                         const char *servername)
4899 {
4900         const char *cservername = canon_servername(servername);
4901
4902         r->version              = driver->version;
4903
4904         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4905         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4906         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4907         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4908
4909         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4910                                driver->architecture,
4911                                driver->version,
4912                                driver->driver_path,
4913                                r->driver_path);
4914
4915         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4916                                driver->architecture,
4917                                driver->version,
4918                                driver->data_file,
4919                                r->data_file);
4920
4921         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4922                                driver->architecture,
4923                                driver->version,
4924                                driver->config_file,
4925                                r->config_file);
4926
4927         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4928                                driver->architecture,
4929                                driver->version,
4930                                driver->help_file,
4931                                r->help_file);
4932
4933         FILL_DRIVER_STRING(mem_ctx,
4934                            driver->monitor_name,
4935                            r->monitor_name);
4936
4937         FILL_DRIVER_STRING(mem_ctx,
4938                            driver->default_datatype,
4939                            r->default_datatype);
4940
4941         return string_array_from_driver_info(mem_ctx,
4942                                              driver->dependent_files,
4943                                              &r->dependent_files,
4944                                              cservername,
4945                                              driver->architecture,
4946                                              driver->version);
4947 }
4948
4949 /********************************************************************
4950  * fill a spoolss_DriverInfo4 struct
4951  ********************************************************************/
4952
4953 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4954                                         struct spoolss_DriverInfo4 *r,
4955                                         const struct spoolss_DriverInfo8 *driver,
4956                                         const char *servername)
4957 {
4958         const char *cservername = canon_servername(servername);
4959         WERROR result;
4960
4961         r->version              = driver->version;
4962
4963         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4964         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4965         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4966         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4967
4968         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4969                                driver->architecture,
4970                                driver->version,
4971                                driver->driver_path,
4972                                r->driver_path);
4973
4974         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4975                                driver->architecture,
4976                                driver->version,
4977                                driver->data_file,
4978                                r->data_file);
4979
4980         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4981                                driver->architecture,
4982                                driver->version,
4983                                driver->config_file,
4984                                r->config_file);
4985
4986         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4987                                driver->architecture,
4988                                driver->version,
4989                                driver->help_file,
4990                                r->help_file);
4991
4992         result = string_array_from_driver_info(mem_ctx,
4993                                                driver->dependent_files,
4994                                                &r->dependent_files,
4995                                                cservername,
4996                                                driver->architecture,
4997                                                driver->version);
4998         if (!W_ERROR_IS_OK(result)) {
4999                 return result;
5000         }
5001
5002         FILL_DRIVER_STRING(mem_ctx,
5003                            driver->monitor_name,
5004                            r->monitor_name);
5005
5006         FILL_DRIVER_STRING(mem_ctx,
5007                            driver->default_datatype,
5008                            r->default_datatype);
5009
5010
5011         result = string_array_from_driver_info(mem_ctx,
5012                                                driver->previous_names,
5013                                                &r->previous_names,
5014                                                NULL, NULL, 0);
5015
5016         return result;
5017 }
5018
5019 /********************************************************************
5020  * fill a spoolss_DriverInfo5 struct
5021  ********************************************************************/
5022
5023 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5024                                         struct spoolss_DriverInfo5 *r,
5025                                         const struct spoolss_DriverInfo8 *driver,
5026                                         const char *servername)
5027 {
5028         const char *cservername = canon_servername(servername);
5029
5030         r->version              = driver->version;
5031
5032         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5033         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5034         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5035         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5036
5037         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5038                                driver->architecture,
5039                                driver->version,
5040                                driver->driver_path,
5041                                r->driver_path);
5042
5043         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5044                                driver->architecture,
5045                                driver->version,
5046                                driver->data_file,
5047                                r->data_file);
5048
5049         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5050                                driver->architecture,
5051                                driver->version,
5052                                driver->config_file,
5053                                r->config_file);
5054
5055         r->driver_attributes    = 0;
5056         r->config_version       = 0;
5057         r->driver_version       = 0;
5058
5059         return WERR_OK;
5060 }
5061 /********************************************************************
5062  * fill a spoolss_DriverInfo6 struct
5063  ********************************************************************/
5064
5065 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5066                                         struct spoolss_DriverInfo6 *r,
5067                                         const struct spoolss_DriverInfo8 *driver,
5068                                         const char *servername)
5069 {
5070         const char *cservername = canon_servername(servername);
5071         WERROR result;
5072
5073         r->version              = driver->version;
5074
5075         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5076         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5077         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5078         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5079
5080         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5081                                driver->architecture,
5082                                driver->version,
5083                                driver->driver_path,
5084                                r->driver_path);
5085
5086         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5087                                driver->architecture,
5088                                driver->version,
5089                                driver->data_file,
5090                                r->data_file);
5091
5092         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5093                                driver->architecture,
5094                                driver->version,
5095                                driver->config_file,
5096                                r->config_file);
5097
5098         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5099                                driver->architecture,
5100                                driver->version,
5101                                driver->help_file,
5102                                r->help_file);
5103
5104         FILL_DRIVER_STRING(mem_ctx,
5105                            driver->monitor_name,
5106                            r->monitor_name);
5107
5108         FILL_DRIVER_STRING(mem_ctx,
5109                            driver->default_datatype,
5110                            r->default_datatype);
5111
5112         result = string_array_from_driver_info(mem_ctx,
5113                                                driver->dependent_files,
5114                                                &r->dependent_files,
5115                                                cservername,
5116                                                driver->architecture,
5117                                                driver->version);
5118         if (!W_ERROR_IS_OK(result)) {
5119                 return result;
5120         }
5121
5122         result = string_array_from_driver_info(mem_ctx,
5123                                                driver->previous_names,
5124                                                &r->previous_names,
5125                                                NULL, NULL, 0);
5126         if (!W_ERROR_IS_OK(result)) {
5127                 return result;
5128         }
5129
5130         r->driver_date          = driver->driver_date;
5131         r->driver_version       = driver->driver_version;
5132
5133         FILL_DRIVER_STRING(mem_ctx,
5134                            driver->manufacturer_name,
5135                            r->manufacturer_name);
5136         FILL_DRIVER_STRING(mem_ctx,
5137                            driver->manufacturer_url,
5138                            r->manufacturer_url);
5139         FILL_DRIVER_STRING(mem_ctx,
5140                            driver->hardware_id,
5141                            r->hardware_id);
5142         FILL_DRIVER_STRING(mem_ctx,
5143                            driver->provider,
5144                            r->provider);
5145
5146         return WERR_OK;
5147 }
5148
5149 /********************************************************************
5150  * fill a spoolss_DriverInfo8 struct
5151  ********************************************************************/
5152
5153 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5154                                         struct spoolss_DriverInfo8 *r,
5155                                         const struct spoolss_DriverInfo8 *driver,
5156                                         const char *servername)
5157 {
5158         const char *cservername = canon_servername(servername);
5159         WERROR result;
5160
5161         r->version              = driver->version;
5162
5163         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5164         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5165         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5166         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5167
5168         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5169                                driver->architecture,
5170                                driver->version,
5171                                driver->driver_path,
5172                                r->driver_path);
5173
5174         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5175                                driver->architecture,
5176                                driver->version,
5177                                driver->data_file,
5178                                r->data_file);
5179
5180         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5181                                driver->architecture,
5182                                driver->version,
5183                                driver->config_file,
5184                                r->config_file);
5185
5186         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5187                                driver->architecture,
5188                                driver->version,
5189                                driver->help_file,
5190                                r->help_file);
5191
5192         FILL_DRIVER_STRING(mem_ctx,
5193                            driver->monitor_name,
5194                            r->monitor_name);
5195
5196         FILL_DRIVER_STRING(mem_ctx,
5197                            driver->default_datatype,
5198                            r->default_datatype);
5199
5200         result = string_array_from_driver_info(mem_ctx,
5201                                                driver->dependent_files,
5202                                                &r->dependent_files,
5203                                                cservername,
5204                                                driver->architecture,
5205                                                driver->version);
5206         if (!W_ERROR_IS_OK(result)) {
5207                 return result;
5208         }
5209
5210         result = string_array_from_driver_info(mem_ctx,
5211                                                driver->previous_names,
5212                                                &r->previous_names,
5213                                                NULL, NULL, 0);
5214         if (!W_ERROR_IS_OK(result)) {
5215                 return result;
5216         }
5217
5218         r->driver_date          = driver->driver_date;
5219         r->driver_version       = driver->driver_version;
5220
5221         FILL_DRIVER_STRING(mem_ctx,
5222                            driver->manufacturer_name,
5223                            r->manufacturer_name);
5224         FILL_DRIVER_STRING(mem_ctx,
5225                            driver->manufacturer_url,
5226                            r->manufacturer_url);
5227         FILL_DRIVER_STRING(mem_ctx,
5228                            driver->hardware_id,
5229                            r->hardware_id);
5230         FILL_DRIVER_STRING(mem_ctx,
5231                            driver->provider,
5232                            r->provider);
5233
5234         FILL_DRIVER_STRING(mem_ctx,
5235                            driver->print_processor,
5236                            r->print_processor);
5237         FILL_DRIVER_STRING(mem_ctx,
5238                            driver->vendor_setup,
5239                            r->vendor_setup);
5240
5241         result = string_array_from_driver_info(mem_ctx,
5242                                                driver->color_profiles,
5243                                                &r->color_profiles,
5244                                                NULL, NULL, 0);
5245         if (!W_ERROR_IS_OK(result)) {
5246                 return result;
5247         }
5248
5249         FILL_DRIVER_STRING(mem_ctx,
5250                            driver->inf_path,
5251                            r->inf_path);
5252
5253         r->printer_driver_attributes    = driver->printer_driver_attributes;
5254
5255         result = string_array_from_driver_info(mem_ctx,
5256                                                driver->core_driver_dependencies,
5257                                                &r->core_driver_dependencies,
5258                                                NULL, NULL, 0);
5259         if (!W_ERROR_IS_OK(result)) {
5260                 return result;
5261         }
5262
5263         r->min_inbox_driver_ver_date    = driver->min_inbox_driver_ver_date;
5264         r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5265
5266         return WERR_OK;
5267 }
5268
5269 #if 0 /* disabled until marshalling issues are resolved - gd */
5270 /********************************************************************
5271  ********************************************************************/
5272
5273 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5274                                           struct spoolss_DriverFileInfo *r,
5275                                           const char *cservername,
5276                                           const char *file_name,
5277                                           enum spoolss_DriverFileType file_type,
5278                                           uint32_t file_version)
5279 {
5280         r->file_name    = talloc_asprintf(mem_ctx, "\\\\%s%s",
5281                                           cservername, file_name);
5282         W_ERROR_HAVE_NO_MEMORY(r->file_name);
5283         r->file_type    = file_type;
5284         r->file_version = file_version;
5285
5286         return WERR_OK;
5287 }
5288
5289 /********************************************************************
5290  ********************************************************************/
5291
5292 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5293                                                  const struct spoolss_DriverInfo8 *driver,
5294                                                  const char *cservername,
5295                                                  struct spoolss_DriverFileInfo **info_p,
5296                                                  uint32_t *count_p)
5297 {
5298         struct spoolss_DriverFileInfo *info = NULL;
5299         uint32_t count = 0;
5300         WERROR result;
5301         uint32_t i;
5302
5303         *info_p = NULL;
5304         *count_p = 0;
5305
5306         if (strlen(driver->driver_path)) {
5307                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5308                                             struct spoolss_DriverFileInfo,
5309                                             count + 1);
5310                 W_ERROR_HAVE_NO_MEMORY(info);
5311                 result = fill_spoolss_DriverFileInfo(info,
5312                                                      &info[count],
5313                                                      cservername,
5314                                                      driver->driver_path,
5315                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5316                                                      0);
5317                 W_ERROR_NOT_OK_RETURN(result);
5318                 count++;
5319         }
5320
5321         if (strlen(driver->config_file)) {
5322                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5323                                             struct spoolss_DriverFileInfo,
5324                                             count + 1);
5325                 W_ERROR_HAVE_NO_MEMORY(info);
5326                 result = fill_spoolss_DriverFileInfo(info,
5327                                                      &info[count],
5328                                                      cservername,
5329                                                      driver->config_file,
5330                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5331                                                      0);
5332                 W_ERROR_NOT_OK_RETURN(result);
5333                 count++;
5334         }
5335
5336         if (strlen(driver->data_file)) {
5337                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5338                                             struct spoolss_DriverFileInfo,
5339                                             count + 1);
5340                 W_ERROR_HAVE_NO_MEMORY(info);
5341                 result = fill_spoolss_DriverFileInfo(info,
5342                                                      &info[count],
5343                                                      cservername,
5344                                                      driver->data_file,
5345                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
5346                                                      0);
5347                 W_ERROR_NOT_OK_RETURN(result);
5348                 count++;
5349         }
5350
5351         if (strlen(driver->help_file)) {
5352                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5353                                             struct spoolss_DriverFileInfo,
5354                                             count + 1);
5355                 W_ERROR_HAVE_NO_MEMORY(info);
5356                 result = fill_spoolss_DriverFileInfo(info,
5357                                                      &info[count],
5358                                                      cservername,
5359                                                      driver->help_file,
5360                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
5361                                                      0);
5362                 W_ERROR_NOT_OK_RETURN(result);
5363                 count++;
5364         }
5365
5366         for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5367                 info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
5368                                             struct spoolss_DriverFileInfo,
5369                                             count + 1);
5370                 W_ERROR_HAVE_NO_MEMORY(info);
5371                 result = fill_spoolss_DriverFileInfo(info,
5372                                                      &info[count],
5373                                                      cservername,
5374                                                      driver->dependent_files[i],
5375                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5376                                                      0);
5377                 W_ERROR_NOT_OK_RETURN(result);
5378                 count++;
5379         }
5380
5381         *info_p = info;
5382         *count_p = count;
5383
5384         return WERR_OK;
5385 }
5386
5387 /********************************************************************
5388  * fill a spoolss_DriverInfo101 struct
5389  ********************************************************************/
5390
5391 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5392                                           struct spoolss_DriverInfo101 *r,
5393                                           const struct spoolss_DriverInfo8 *driver,
5394                                           const char *servername)
5395 {
5396         const char *cservername = canon_servername(servername);
5397         WERROR result;
5398
5399         r->version              = driver->version;
5400
5401         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5402         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5403         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5404         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5405
5406         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5407                                                     cservername,
5408                                                     &r->file_info,
5409                                                     &r->file_count);
5410         if (!W_ERROR_IS_OK(result)) {
5411                 return result;
5412         }
5413
5414         FILL_DRIVER_STRING(mem_ctx,
5415                            driver->monitor_name,
5416                            r->monitor_name);
5417
5418         FILL_DRIVER_STRING(mem_ctx,
5419                            driver->default_datatype,
5420                            r->default_datatype);
5421
5422         result = string_array_from_driver_info(mem_ctx,
5423                                                driver->previous_names,
5424                                                &r->previous_names,
5425                                                NULL, NULL, 0);
5426         if (!W_ERROR_IS_OK(result)) {
5427                 return result;
5428         }
5429
5430         r->driver_date          = driver->driver_date;
5431         r->driver_version       = driver->driver_version;
5432
5433         FILL_DRIVER_STRING(mem_ctx,
5434                            driver->manufacturer_name,
5435                            r->manufacturer_name);
5436         FILL_DRIVER_STRING(mem_ctx,
5437                            driver->manufacturer_url,
5438                            r->manufacturer_url);
5439         FILL_DRIVER_STRING(mem_ctx,
5440                            driver->hardware_id,
5441                            r->hardware_id);
5442         FILL_DRIVER_STRING(mem_ctx,
5443                            driver->provider,
5444                            r->provider);
5445
5446         return WERR_OK;
5447 }
5448 #endif
5449 /********************************************************************
5450  ********************************************************************/
5451
5452 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5453                                                   const struct auth_serversupplied_info *session_info,
5454                                                   struct messaging_context *msg_ctx,
5455                                                   uint32_t level,
5456                                                   union spoolss_DriverInfo *r,
5457                                                   int snum,
5458                                                   const char *servername,
5459                                                   const char *architecture,
5460                                                   uint32_t version)
5461 {
5462         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5463         struct spoolss_DriverInfo8 *driver;
5464         WERROR result;
5465
5466         if (level == 101) {
5467                 return WERR_UNKNOWN_LEVEL;
5468         }
5469
5470         result = winreg_get_printer(mem_ctx,
5471                                     session_info,
5472                                     msg_ctx,
5473                                     lp_const_servicename(snum),
5474                                     &pinfo2);
5475
5476         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5477                 win_errstr(result)));
5478
5479         if (!W_ERROR_IS_OK(result)) {
5480                 return WERR_INVALID_PRINTER_NAME;
5481         }
5482
5483         result = winreg_get_driver(mem_ctx, session_info, msg_ctx,
5484                                    architecture,
5485                                    pinfo2->drivername, version, &driver);
5486
5487         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5488                 win_errstr(result)));
5489
5490         if (!W_ERROR_IS_OK(result)) {
5491                 /*
5492                  * Is this a W2k client ?
5493                  */
5494
5495                 if (version < 3) {
5496                         talloc_free(pinfo2);
5497                         return WERR_UNKNOWN_PRINTER_DRIVER;
5498                 }
5499
5500                 /* Yes - try again with a WinNT driver. */
5501                 version = 2;
5502                 result = winreg_get_driver(mem_ctx, session_info, msg_ctx,
5503                                            architecture,
5504                                            pinfo2->drivername,
5505                                            version, &driver);
5506                 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5507                         win_errstr(result)));
5508                 if (!W_ERROR_IS_OK(result)) {
5509                         talloc_free(pinfo2);
5510                         return WERR_UNKNOWN_PRINTER_DRIVER;
5511                 }
5512         }
5513
5514         switch (level) {
5515         case 1:
5516                 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5517                 break;
5518         case 2:
5519                 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5520                 break;
5521         case 3:
5522                 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5523                 break;
5524         case 4:
5525                 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5526                 break;
5527         case 5:
5528                 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5529                 break;
5530         case 6:
5531                 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5532                 break;
5533         case 8:
5534                 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5535                 break;
5536 #if 0 /* disabled until marshalling issues are resolved - gd */
5537         case 101:
5538                 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5539                 break;
5540 #endif
5541         default:
5542                 result = WERR_UNKNOWN_LEVEL;
5543                 break;
5544         }
5545
5546         talloc_free(pinfo2);
5547         talloc_free(driver);
5548
5549         return result;
5550 }
5551
5552 /****************************************************************
5553  _spoolss_GetPrinterDriver2
5554 ****************************************************************/
5555
5556 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5557                                   struct spoolss_GetPrinterDriver2 *r)
5558 {
5559         struct printer_handle *printer;
5560         WERROR result;
5561
5562         int snum;
5563
5564         /* that's an [in out] buffer */
5565
5566         if (!r->in.buffer && (r->in.offered != 0)) {
5567                 return WERR_INVALID_PARAM;
5568         }
5569
5570         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5571
5572         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5573                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5574                 return WERR_INVALID_PRINTER_NAME;
5575         }
5576
5577         *r->out.needed = 0;
5578         *r->out.server_major_version = 0;
5579         *r->out.server_minor_version = 0;
5580
5581         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5582                 return WERR_BADFID;
5583         }
5584
5585         result = construct_printer_driver_info_level(p->mem_ctx,
5586                                                      get_session_info_system(),
5587                                                      p->msg_ctx,
5588                                                      r->in.level, r->out.info,
5589                                                      snum, printer->servername,
5590                                                      r->in.architecture,
5591                                                      r->in.client_major_version);
5592         if (!W_ERROR_IS_OK(result)) {
5593                 TALLOC_FREE(r->out.info);
5594                 return result;
5595         }
5596
5597         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5598                                                r->out.info, r->in.level);
5599         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5600
5601         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5602 }
5603
5604
5605 /****************************************************************
5606  _spoolss_StartPagePrinter
5607 ****************************************************************/
5608
5609 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5610                                  struct spoolss_StartPagePrinter *r)
5611 {
5612         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5613
5614         if (!Printer) {
5615                 DEBUG(3,("_spoolss_StartPagePrinter: "
5616                         "Error in startpageprinter printer handle\n"));
5617                 return WERR_BADFID;
5618         }
5619
5620         Printer->page_started = true;
5621         return WERR_OK;
5622 }
5623
5624 /****************************************************************
5625  _spoolss_EndPagePrinter
5626 ****************************************************************/
5627
5628 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5629                                struct spoolss_EndPagePrinter *r)
5630 {
5631         int snum;
5632
5633         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5634
5635         if (!Printer) {
5636                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5637                         OUR_HANDLE(r->in.handle)));
5638                 return WERR_BADFID;
5639         }
5640
5641         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5642                 return WERR_BADFID;
5643
5644         Printer->page_started = false;
5645         print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5646
5647         return WERR_OK;
5648 }
5649
5650 /****************************************************************
5651  _spoolss_StartDocPrinter
5652 ****************************************************************/
5653
5654 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5655                                 struct spoolss_StartDocPrinter *r)
5656 {
5657         struct spoolss_DocumentInfo1 *info_1;
5658         int snum;
5659         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5660         WERROR werr;
5661
5662         if (!Printer) {
5663                 DEBUG(2,("_spoolss_StartDocPrinter: "
5664                         "Invalid handle (%s:%u:%u)\n",
5665                         OUR_HANDLE(r->in.handle)));
5666                 return WERR_BADFID;
5667         }
5668
5669         if (Printer->jobid) {
5670                 DEBUG(2, ("_spoolss_StartDocPrinter: "
5671                           "StartDocPrinter called twice! "
5672                           "(existing jobid = %d)\n", Printer->jobid));
5673                 return WERR_INVALID_HANDLE;
5674         }
5675
5676         if (r->in.level != 1) {
5677                 return WERR_UNKNOWN_LEVEL;
5678         }
5679
5680         info_1 = r->in.info.info1;
5681
5682         /*
5683          * a nice thing with NT is it doesn't listen to what you tell it.
5684          * when asked to send _only_ RAW datas, it tries to send datas
5685          * in EMF format.
5686          *
5687          * So I add checks like in NT Server ...
5688          */
5689
5690         if (info_1->datatype) {
5691                 if (strcmp(info_1->datatype, "RAW") != 0) {
5692                         *r->out.job_id = 0;
5693                         return WERR_INVALID_DATATYPE;
5694                 }
5695         }
5696
5697         /* get the share number of the printer */
5698         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5699                 return WERR_BADFID;
5700         }
5701
5702         werr = print_job_start(p->session_info,
5703                                p->msg_ctx,
5704                                p->client_id->name,
5705                                snum,
5706                                info_1->document_name,
5707                                info_1->output_file,
5708                                Printer->devmode,
5709                                &Printer->jobid);
5710
5711         /* An error occured in print_job_start() so return an appropriate
5712            NT error code. */
5713
5714         if (!W_ERROR_IS_OK(werr)) {
5715                 return werr;
5716         }
5717
5718         Printer->document_started = true;
5719         *r->out.job_id = Printer->jobid;
5720
5721         return WERR_OK;
5722 }
5723
5724 /****************************************************************
5725  _spoolss_EndDocPrinter
5726 ****************************************************************/
5727
5728 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5729                               struct spoolss_EndDocPrinter *r)
5730 {
5731         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5732         NTSTATUS status;
5733         int snum;
5734
5735         if (!Printer) {
5736                 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5737                         OUR_HANDLE(r->in.handle)));
5738                 return WERR_BADFID;
5739         }
5740
5741         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5742                 return WERR_BADFID;
5743         }
5744
5745         Printer->document_started = false;
5746         status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5747         if (!NT_STATUS_IS_OK(status)) {
5748                 DEBUG(2, ("_spoolss_EndDocPrinter: "
5749                           "print_job_end failed [%s]\n",
5750                           nt_errstr(status)));
5751         }
5752
5753         Printer->jobid = 0;
5754         return ntstatus_to_werror(status);
5755 }
5756
5757 /****************************************************************
5758  _spoolss_WritePrinter
5759 ****************************************************************/
5760
5761 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5762                              struct spoolss_WritePrinter *r)
5763 {
5764         ssize_t buffer_written;
5765         int snum;
5766         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5767
5768         if (!Printer) {
5769                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5770                         OUR_HANDLE(r->in.handle)));
5771                 *r->out.num_written = r->in._data_size;
5772                 return WERR_BADFID;
5773         }
5774
5775         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5776                 return WERR_BADFID;
5777
5778         /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5779         buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5780                                                    snum, Printer->jobid,
5781                                                    (const char *)r->in.data.data,
5782                                                    (size_t)r->in._data_size);
5783         if (buffer_written == (ssize_t)-1) {
5784                 *r->out.num_written = 0;
5785                 if (errno == ENOSPC)
5786                         return WERR_NO_SPOOL_SPACE;
5787                 else
5788                         return WERR_ACCESS_DENIED;
5789         }
5790
5791         *r->out.num_written = r->in._data_size;
5792
5793         return WERR_OK;
5794 }
5795
5796 /********************************************************************
5797  * api_spoolss_getprinter
5798  * called from the spoolss dispatcher
5799  *
5800  ********************************************************************/
5801
5802 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5803                               struct pipes_struct *p)
5804 {
5805         const struct auth_serversupplied_info *session_info = p->session_info;
5806         int snum;
5807         WERROR errcode = WERR_BADFUNC;
5808         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5809
5810         if (!Printer) {
5811                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5812                         OUR_HANDLE(handle)));
5813                 return WERR_BADFID;
5814         }
5815
5816         if (!get_printer_snum(p, handle, &snum, NULL))
5817                 return WERR_BADFID;
5818
5819         switch (command) {
5820         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5821                 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
5822                 break;
5823         case SPOOLSS_PRINTER_CONTROL_RESUME:
5824         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5825                 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
5826                 break;
5827         case SPOOLSS_PRINTER_CONTROL_PURGE:
5828                 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
5829                 break;
5830         default:
5831                 return WERR_UNKNOWN_LEVEL;
5832         }
5833
5834         return errcode;
5835 }
5836
5837
5838 /****************************************************************
5839  _spoolss_AbortPrinter
5840  * From MSDN: "Deletes printer's spool file if printer is configured
5841  * for spooling"
5842 ****************************************************************/
5843
5844 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
5845                              struct spoolss_AbortPrinter *r)
5846 {
5847         struct printer_handle   *Printer = find_printer_index_by_hnd(p, r->in.handle);
5848         int             snum;
5849         WERROR          errcode = WERR_OK;
5850
5851         if (!Printer) {
5852                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5853                         OUR_HANDLE(r->in.handle)));
5854                 return WERR_BADFID;
5855         }
5856
5857         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5858                 return WERR_BADFID;
5859
5860         if (!Printer->document_started) {
5861                 return WERR_SPL_NO_STARTDOC;
5862         }
5863
5864         errcode = print_job_delete(p->session_info,
5865                                    p->msg_ctx,
5866                                    snum,
5867                                    Printer->jobid);
5868
5869         return errcode;
5870 }
5871
5872 /********************************************************************
5873  * called by spoolss_api_setprinter
5874  * when updating a printer description
5875  ********************************************************************/
5876
5877 static WERROR update_printer_sec(struct policy_handle *handle,
5878                                  struct pipes_struct *p,
5879                                  struct sec_desc_buf *secdesc_ctr)
5880 {
5881         struct spoolss_security_descriptor *new_secdesc = NULL;
5882         struct spoolss_security_descriptor *old_secdesc = NULL;
5883         const char *printer;
5884         WERROR result;
5885         int snum;
5886
5887         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5888
5889         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5890                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5891                          OUR_HANDLE(handle)));
5892
5893                 result = WERR_BADFID;
5894                 goto done;
5895         }
5896
5897         if (secdesc_ctr == NULL) {
5898                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5899                 result = WERR_INVALID_PARAM;
5900                 goto done;
5901         }
5902         printer = lp_const_servicename(snum);
5903
5904         /* Check the user has permissions to change the security
5905            descriptor.  By experimentation with two NT machines, the user
5906            requires Full Access to the printer to change security
5907            information. */
5908
5909         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5910                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5911                 result = WERR_ACCESS_DENIED;
5912                 goto done;
5913         }
5914
5915         /* NT seems to like setting the security descriptor even though
5916            nothing may have actually changed. */
5917         result = winreg_get_printer_secdesc(p->mem_ctx,
5918                                             get_session_info_system(),
5919                                             p->msg_ctx,
5920                                             printer,
5921                                             &old_secdesc);
5922         if (!W_ERROR_IS_OK(result)) {
5923                 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc() failed\n"));
5924                 result = WERR_BADFID;
5925                 goto done;
5926         }
5927
5928         if (DEBUGLEVEL >= 10) {
5929                 struct security_acl *the_acl;
5930                 int i;
5931
5932                 the_acl = old_secdesc->dacl;
5933                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5934                            printer, the_acl->num_aces));
5935
5936                 for (i = 0; i < the_acl->num_aces; i++) {
5937                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5938                                            &the_acl->aces[i].trustee),
5939                                   the_acl->aces[i].access_mask));
5940                 }
5941
5942                 the_acl = secdesc_ctr->sd->dacl;
5943
5944                 if (the_acl) {
5945                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5946                                    printer, the_acl->num_aces));
5947
5948                         for (i = 0; i < the_acl->num_aces; i++) {
5949                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5950                                                    &the_acl->aces[i].trustee),
5951                                            the_acl->aces[i].access_mask));
5952                         }
5953                 } else {
5954                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5955                 }
5956         }
5957
5958         new_secdesc = sec_desc_merge(p->mem_ctx, secdesc_ctr->sd, old_secdesc);
5959         if (new_secdesc == NULL) {
5960                 result = WERR_NOMEM;
5961                 goto done;
5962         }
5963
5964         if (security_descriptor_equal(new_secdesc, old_secdesc)) {
5965                 result = WERR_OK;
5966                 goto done;
5967         }
5968
5969         result = winreg_set_printer_secdesc(p->mem_ctx,
5970                                             get_session_info_system(),
5971                                             p->msg_ctx,
5972                                             printer,
5973                                             new_secdesc);
5974
5975  done:
5976         return result;
5977 }
5978
5979 /********************************************************************
5980  Canonicalize printer info from a client
5981  ********************************************************************/
5982
5983 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
5984                              struct spoolss_SetPrinterInfo2 *info2,
5985                              int snum)
5986 {
5987         fstring printername;
5988         const char *p;
5989
5990         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5991                 "portname=%s drivername=%s comment=%s location=%s\n",
5992                 info2->servername, info2->printername, info2->sharename,
5993                 info2->portname, info2->drivername, info2->comment,
5994                 info2->location));
5995
5996         /* we force some elements to "correct" values */
5997         info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
5998         if (info2->servername == NULL) {
5999                 return false;
6000         }
6001         info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6002         if (info2->sharename == NULL) {
6003                 return false;
6004         }
6005
6006         /* check to see if we allow printername != sharename */
6007         if (lp_force_printername(snum)) {
6008                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6009                                         global_myname(), info2->sharename);
6010         } else {
6011                 /* make sure printername is in \\server\printername format */
6012                 fstrcpy(printername, info2->printername);
6013                 p = printername;
6014                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6015                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6016                                 p++;
6017                 }
6018
6019                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6020                                         global_myname(), p);
6021         }
6022         if (info2->printername == NULL) {
6023                 return false;
6024         }
6025
6026         info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6027         info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6028
6029         return true;
6030 }
6031
6032 /****************************************************************************
6033 ****************************************************************************/
6034
6035 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6036 {
6037         char *cmd = lp_addport_cmd();
6038         char *command = NULL;
6039         int ret;
6040         bool is_print_op = false;
6041
6042         if ( !*cmd ) {
6043                 return WERR_ACCESS_DENIED;
6044         }
6045
6046         command = talloc_asprintf(ctx,
6047                         "%s \"%s\" \"%s\"", cmd, portname, uri );
6048         if (!command) {
6049                 return WERR_NOMEM;
6050         }
6051
6052         if ( token )
6053                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6054
6055         DEBUG(10,("Running [%s]\n", command));
6056
6057         /********* BEGIN SePrintOperatorPrivilege **********/
6058
6059         if ( is_print_op )
6060                 become_root();
6061
6062         ret = smbrun(command, NULL);
6063
6064         if ( is_print_op )
6065                 unbecome_root();
6066
6067         /********* END SePrintOperatorPrivilege **********/
6068
6069         DEBUGADD(10,("returned [%d]\n", ret));
6070
6071         TALLOC_FREE(command);
6072
6073         if ( ret != 0 ) {
6074                 return WERR_ACCESS_DENIED;
6075         }
6076
6077         return WERR_OK;
6078 }
6079
6080 /****************************************************************************
6081 ****************************************************************************/
6082
6083 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6084                              struct spoolss_SetPrinterInfo2 *info2,
6085                              const char *remote_machine,
6086                              struct messaging_context *msg_ctx)
6087 {
6088         char *cmd = lp_addprinter_cmd();
6089         char **qlines;
6090         char *command = NULL;
6091         int numlines;
6092         int ret;
6093         int fd;
6094         bool is_print_op = false;
6095
6096         if (!remote_machine) {
6097                 return false;
6098         }
6099
6100         command = talloc_asprintf(ctx,
6101                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6102                         cmd, info2->printername, info2->sharename,
6103                         info2->portname, info2->drivername,
6104                         info2->location, info2->comment, remote_machine);
6105         if (!command) {
6106                 return false;
6107         }
6108
6109         if ( token )
6110                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6111
6112         DEBUG(10,("Running [%s]\n", command));
6113
6114         /********* BEGIN SePrintOperatorPrivilege **********/
6115
6116         if ( is_print_op )
6117                 become_root();
6118
6119         if ( (ret = smbrun(command, &fd)) == 0 ) {
6120                 /* Tell everyone we updated smb.conf. */
6121                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6122         }
6123
6124         if ( is_print_op )
6125                 unbecome_root();
6126
6127         /********* END SePrintOperatorPrivilege **********/
6128
6129         DEBUGADD(10,("returned [%d]\n", ret));
6130
6131         TALLOC_FREE(command);
6132
6133         if ( ret != 0 ) {
6134                 if (fd != -1)
6135                         close(fd);
6136                 return false;
6137         }
6138
6139         /* reload our services immediately */
6140         become_root();
6141         reload_services(msg_ctx, -1, false);
6142         unbecome_root();
6143
6144         numlines = 0;
6145         /* Get lines and convert them back to dos-codepage */
6146         qlines = fd_lines_load(fd, &numlines, 0, NULL);
6147         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6148         close(fd);
6149
6150         /* Set the portname to what the script says the portname should be. */
6151         /* but don't require anything to be return from the script exit a good error code */
6152
6153         if (numlines) {
6154                 /* Set the portname to what the script says the portname should be. */
6155                 info2->portname = talloc_strdup(ctx, qlines[0]);
6156                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6157         }
6158
6159         TALLOC_FREE(qlines);
6160         return true;
6161 }
6162
6163 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6164                                const struct auth_serversupplied_info *session_info,
6165                                struct messaging_context *msg_ctx,
6166                                int snum,
6167                                struct spoolss_SetPrinterInfo2 *printer,
6168                                struct spoolss_PrinterInfo2 *old_printer)
6169 {
6170         bool force_update = (old_printer == NULL);
6171         const char *dnsdomname;
6172         const char *longname;
6173         const char *uncname;
6174         const char *spooling;
6175         DATA_BLOB buffer;
6176         WERROR result = WERR_OK;
6177
6178         if (force_update || !strequal(printer->drivername, old_printer->drivername)) {
6179                 push_reg_sz(mem_ctx, &buffer, printer->drivername);
6180                 winreg_set_printer_dataex(mem_ctx,
6181                                           session_info,
6182                                           msg_ctx,
6183                                           printer->sharename,
6184                                           SPOOL_DSSPOOLER_KEY,
6185                                           SPOOL_REG_DRIVERNAME,
6186                                           REG_SZ,
6187                                           buffer.data,
6188                                           buffer.length);
6189
6190                 if (!force_update) {
6191                         DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6192                                 printer->drivername));
6193
6194                         notify_printer_driver(server_event_context(), msg_ctx,
6195                                               snum, printer->drivername ?
6196                                               printer->drivername : "");
6197                 }
6198         }
6199
6200         if (force_update || !strequal(printer->comment, old_printer->comment)) {
6201                 push_reg_sz(mem_ctx, &buffer, printer->comment);
6202                 winreg_set_printer_dataex(mem_ctx,
6203                                           session_info,
6204                                           msg_ctx,
6205                                           printer->sharename,
6206                                           SPOOL_DSSPOOLER_KEY,
6207                                           SPOOL_REG_DESCRIPTION,
6208                                           REG_SZ,
6209                                           buffer.data,
6210                                           buffer.length);
6211
6212                 if (!force_update) {
6213                         notify_printer_comment(server_event_context(), msg_ctx,
6214                                                snum, printer->comment ?
6215                                                printer->comment : "");
6216                 }
6217         }
6218
6219         if (force_update || !strequal(printer->sharename, old_printer->sharename)) {
6220                 push_reg_sz(mem_ctx, &buffer, printer->sharename);
6221                 winreg_set_printer_dataex(mem_ctx,
6222                                           session_info,
6223                                           msg_ctx,
6224                                           printer->sharename,
6225                                           SPOOL_DSSPOOLER_KEY,
6226                                           SPOOL_REG_PRINTSHARENAME,
6227                                           REG_SZ,
6228                                           buffer.data,
6229                                           buffer.length);
6230
6231                 if (!force_update) {
6232                         notify_printer_sharename(server_event_context(),
6233                                                  msg_ctx,
6234                                                  snum, printer->sharename ?
6235                                                  printer->sharename : "");
6236                 }
6237         }
6238
6239         if (force_update || !strequal(printer->printername, old_printer->printername)) {
6240                 const char *p;
6241
6242                 p = strrchr(printer->printername, '\\' );
6243                 if (p != NULL) {
6244                         p++;
6245                 } else {
6246                         p = printer->printername;
6247                 }
6248
6249                 push_reg_sz(mem_ctx, &buffer, p);
6250                 winreg_set_printer_dataex(mem_ctx,
6251                                           session_info,
6252                                           msg_ctx,
6253                                           printer->sharename,
6254                                           SPOOL_DSSPOOLER_KEY,
6255                                           SPOOL_REG_PRINTERNAME,
6256                                           REG_SZ,
6257                                           buffer.data,
6258                                           buffer.length);
6259
6260                 if (!force_update) {
6261                         notify_printer_printername(server_event_context(),
6262                                                    msg_ctx, snum, p ? p : "");
6263                 }
6264         }
6265
6266         if (force_update || !strequal(printer->portname, old_printer->portname)) {
6267                 push_reg_sz(mem_ctx, &buffer, printer->portname);
6268                 winreg_set_printer_dataex(mem_ctx,
6269                                           session_info,
6270                                           msg_ctx,
6271                                           printer->sharename,
6272                                           SPOOL_DSSPOOLER_KEY,
6273                                           SPOOL_REG_PORTNAME,
6274                                           REG_SZ,
6275                                           buffer.data,
6276                                           buffer.length);
6277
6278                 if (!force_update) {
6279                         notify_printer_port(server_event_context(),
6280                                             msg_ctx, snum, printer->portname ?
6281                                             printer->portname : "");
6282                 }
6283         }
6284
6285         if (force_update || !strequal(printer->location, old_printer->location)) {
6286                 push_reg_sz(mem_ctx, &buffer, printer->location);
6287                 winreg_set_printer_dataex(mem_ctx,
6288                                           session_info,
6289                                           msg_ctx,
6290                                           printer->sharename,
6291                                           SPOOL_DSSPOOLER_KEY,
6292                                           SPOOL_REG_LOCATION,
6293                                           REG_SZ,
6294                                           buffer.data,
6295                                           buffer.length);
6296
6297                 if (!force_update) {
6298                         notify_printer_location(server_event_context(),
6299                                                 msg_ctx, snum,
6300                                                 printer->location ?
6301                                                 printer->location : "");
6302                 }
6303         }
6304
6305         if (force_update || !strequal(printer->sepfile, old_printer->sepfile)) {
6306                 push_reg_sz(mem_ctx, &buffer, printer->sepfile);
6307                 winreg_set_printer_dataex(mem_ctx,
6308                                           session_info,
6309                                           msg_ctx,
6310                                           printer->sharename,
6311                                           SPOOL_DSSPOOLER_KEY,
6312                                           SPOOL_REG_PRINTSEPARATORFILE,
6313                                           REG_SZ,
6314                                           buffer.data,
6315                                           buffer.length);
6316
6317                 if (!force_update) {
6318                         notify_printer_sepfile(server_event_context(),
6319                                                msg_ctx, snum,
6320                                                printer->sepfile ?
6321                                                printer->sepfile : "");
6322                 }
6323         }
6324
6325         if (force_update || printer->starttime != old_printer->starttime) {
6326                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6327                 SIVAL(buffer.data, 0, printer->starttime);
6328                 winreg_set_printer_dataex(mem_ctx,
6329                                           session_info,
6330                                           msg_ctx,
6331                                           printer->sharename,
6332                                           SPOOL_DSSPOOLER_KEY,
6333                                           SPOOL_REG_PRINTSTARTTIME,
6334                                           REG_DWORD,
6335                                           buffer.data,
6336                                           buffer.length);
6337         }
6338
6339         if (force_update || printer->untiltime != old_printer->untiltime) {
6340                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6341                 SIVAL(buffer.data, 0, printer->untiltime);
6342                 winreg_set_printer_dataex(mem_ctx,
6343                                           session_info,
6344                                           msg_ctx,
6345                                           printer->sharename,
6346                                           SPOOL_DSSPOOLER_KEY,
6347                                           SPOOL_REG_PRINTENDTIME,
6348                                           REG_DWORD,
6349                                           buffer.data,
6350                                           buffer.length);
6351         }
6352
6353         if (force_update || printer->priority != old_printer->priority) {
6354                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6355                 SIVAL(buffer.data, 0, printer->priority);
6356                 winreg_set_printer_dataex(mem_ctx,
6357                                           session_info,
6358                                           msg_ctx,
6359                                           printer->sharename,
6360                                           SPOOL_DSSPOOLER_KEY,
6361                                           SPOOL_REG_PRIORITY,
6362                                           REG_DWORD,
6363                                           buffer.data,
6364                                           buffer.length);
6365         }
6366
6367         if (force_update || printer->attributes != old_printer->attributes) {
6368                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6369                 SIVAL(buffer.data, 0, (printer->attributes &
6370                                        PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6371                 winreg_set_printer_dataex(mem_ctx,
6372                                           session_info,
6373                                           msg_ctx,
6374                                           printer->sharename,
6375                                           SPOOL_DSSPOOLER_KEY,
6376                                           SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6377                                           REG_DWORD,
6378                                           buffer.data,
6379                                           buffer.length);
6380
6381                 switch (printer->attributes & 0x3) {
6382                         case 0:
6383                                 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6384                                 break;
6385                         case 1:
6386                                 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6387                                 break;
6388                         case 2:
6389                                 spooling = SPOOL_REGVAL_PRINTDIRECT;
6390                                 break;
6391                         default:
6392                                 spooling = "unknown";
6393                 }
6394                 push_reg_sz(mem_ctx, &buffer, spooling);
6395                 winreg_set_printer_dataex(mem_ctx,
6396                                           session_info,
6397                                           msg_ctx,
6398                                           printer->sharename,
6399                                           SPOOL_DSSPOOLER_KEY,
6400                                           SPOOL_REG_PRINTSPOOLING,
6401                                           REG_SZ,
6402                                           buffer.data,
6403                                           buffer.length);
6404         }
6405
6406         push_reg_sz(mem_ctx, &buffer, global_myname());
6407         winreg_set_printer_dataex(mem_ctx,
6408                                   session_info,
6409                                   msg_ctx,
6410                                   printer->sharename,
6411                                   SPOOL_DSSPOOLER_KEY,
6412                                   SPOOL_REG_SHORTSERVERNAME,
6413                                   REG_SZ,
6414                                   buffer.data,
6415                                   buffer.length);
6416
6417         dnsdomname = get_mydnsfullname();
6418         if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6419                 longname = talloc_strdup(mem_ctx, dnsdomname);
6420         } else {
6421                 longname = talloc_strdup(mem_ctx, global_myname());
6422         }
6423         if (longname == NULL) {
6424                 result = WERR_NOMEM;
6425                 goto done;
6426         }
6427
6428         push_reg_sz(mem_ctx, &buffer, longname);
6429         winreg_set_printer_dataex(mem_ctx,
6430                                   session_info,
6431                                   msg_ctx,
6432                                   printer->sharename,
6433                                   SPOOL_DSSPOOLER_KEY,
6434                                   SPOOL_REG_SERVERNAME,
6435                                   REG_SZ,
6436                                   buffer.data,
6437                                   buffer.length);
6438
6439         uncname = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6440                                   global_myname(), printer->sharename);
6441         push_reg_sz(mem_ctx, &buffer, uncname);
6442         winreg_set_printer_dataex(mem_ctx,
6443                                   session_info,
6444                                   msg_ctx,
6445                                   printer->sharename,
6446                                   SPOOL_DSSPOOLER_KEY,
6447                                   SPOOL_REG_UNCNAME,
6448                                   REG_SZ,
6449                                   buffer.data,
6450                                   buffer.length);
6451
6452 done:
6453         return result;
6454 }
6455
6456 /********************************************************************
6457  * Called by spoolss_api_setprinter
6458  * when updating a printer description.
6459  ********************************************************************/
6460
6461 static WERROR update_printer(struct pipes_struct *p,
6462                              struct policy_handle *handle,
6463                              struct spoolss_SetPrinterInfoCtr *info_ctr,
6464                              struct spoolss_DeviceMode *devmode)
6465 {
6466         uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6467         struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6468         struct spoolss_PrinterInfo2 *old_printer;
6469         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6470         int snum;
6471         WERROR result = WERR_OK;
6472         TALLOC_CTX *tmp_ctx;
6473
6474         DEBUG(8,("update_printer\n"));
6475
6476         tmp_ctx = talloc_new(p->mem_ctx);
6477         if (tmp_ctx == NULL) {
6478                 return WERR_NOMEM;
6479         }
6480
6481         if (!Printer) {
6482                 result = WERR_BADFID;
6483                 goto done;
6484         }
6485
6486         if (!get_printer_snum(p, handle, &snum, NULL)) {
6487                 result = WERR_BADFID;
6488                 goto done;
6489         }
6490
6491         result = winreg_get_printer(tmp_ctx,
6492                                     get_session_info_system(),
6493                                     p->msg_ctx,
6494                                     lp_const_servicename(snum),
6495                                     &old_printer);
6496         if (!W_ERROR_IS_OK(result)) {
6497                 result = WERR_BADFID;
6498                 goto done;
6499         }
6500
6501         /* Do sanity check on the requested changes for Samba */
6502         if (!check_printer_ok(tmp_ctx, printer, snum)) {
6503                 result = WERR_INVALID_PARAM;
6504                 goto done;
6505         }
6506
6507         /* FIXME!!! If the driver has changed we really should verify that
6508            it is installed before doing much else   --jerry */
6509
6510         /* Check calling user has permission to update printer description */
6511         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6512                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6513                 result = WERR_ACCESS_DENIED;
6514                 goto done;
6515         }
6516
6517         /* Call addprinter hook */
6518         /* Check changes to see if this is really needed */
6519
6520         if (*lp_addprinter_cmd() &&
6521                         (!strequal(printer->drivername, old_printer->drivername) ||
6522                          !strequal(printer->comment, old_printer->comment) ||
6523                          !strequal(printer->portname, old_printer->portname) ||
6524                          !strequal(printer->location, old_printer->location)) )
6525         {
6526                 /* add_printer_hook() will call reload_services() */
6527                 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6528                                       printer, p->client_id->addr,
6529                                       p->msg_ctx)) {
6530                         result = WERR_ACCESS_DENIED;
6531                         goto done;
6532                 }
6533         }
6534
6535         update_dsspooler(tmp_ctx,
6536                          get_session_info_system(),
6537                          p->msg_ctx,
6538                          snum,
6539                          printer,
6540                          old_printer);
6541
6542         printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6543
6544         if (devmode == NULL) {
6545                 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6546         }
6547         result = winreg_update_printer(tmp_ctx,
6548                                        get_session_info_system(),
6549                                        p->msg_ctx,
6550                                        printer->sharename,
6551                                        printer_mask,
6552                                        printer,
6553                                        devmode,
6554                                        NULL);
6555
6556 done:
6557         talloc_free(tmp_ctx);
6558
6559         return result;
6560 }
6561
6562 /****************************************************************************
6563 ****************************************************************************/
6564 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6565                                            struct policy_handle *handle,
6566                                            struct spoolss_SetPrinterInfo7 *info7)
6567 {
6568 #ifdef HAVE_ADS
6569         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6570         WERROR result;
6571         int snum;
6572         struct printer_handle *Printer;
6573
6574         if ( lp_security() != SEC_ADS ) {
6575                 return WERR_UNKNOWN_LEVEL;
6576         }
6577
6578         Printer = find_printer_index_by_hnd(p, handle);
6579
6580         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6581
6582         if (!Printer)
6583                 return WERR_BADFID;
6584
6585         if (!get_printer_snum(p, handle, &snum, NULL))
6586                 return WERR_BADFID;
6587
6588         result = winreg_get_printer(p->mem_ctx,
6589                                     get_session_info_system(),
6590                                     p->msg_ctx,
6591                                     lp_servicename(snum),
6592                                     &pinfo2);
6593         if (!W_ERROR_IS_OK(result)) {
6594                 return WERR_BADFID;
6595         }
6596
6597         nt_printer_publish(pinfo2,
6598                            get_session_info_system(),
6599                            p->msg_ctx,
6600                            pinfo2,
6601                            info7->action);
6602
6603         TALLOC_FREE(pinfo2);
6604         return WERR_OK;
6605 #else
6606         return WERR_UNKNOWN_LEVEL;
6607 #endif
6608 }
6609
6610 /********************************************************************
6611  ********************************************************************/
6612
6613 static WERROR update_printer_devmode(struct pipes_struct *p,
6614                                      struct policy_handle *handle,
6615                                      struct spoolss_DeviceMode *devmode)
6616 {
6617         int snum;
6618         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6619         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6620
6621         DEBUG(8,("update_printer_devmode\n"));
6622
6623         if (!Printer) {
6624                 return WERR_BADFID;
6625         }
6626
6627         if (!get_printer_snum(p, handle, &snum, NULL)) {
6628                 return WERR_BADFID;
6629         }
6630
6631         /* Check calling user has permission to update printer description */
6632         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6633                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6634                 return WERR_ACCESS_DENIED;
6635         }
6636
6637         return winreg_update_printer(p->mem_ctx,
6638                                      get_session_info_system(),
6639                                      p->msg_ctx,
6640                                      lp_const_servicename(snum),
6641                                      info2_mask,
6642                                      NULL,
6643                                      devmode,
6644                                      NULL);
6645 }
6646
6647
6648 /****************************************************************
6649  _spoolss_SetPrinter
6650 ****************************************************************/
6651
6652 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6653                            struct spoolss_SetPrinter *r)
6654 {
6655         WERROR result;
6656
6657         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6658
6659         if (!Printer) {
6660                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6661                         OUR_HANDLE(r->in.handle)));
6662                 return WERR_BADFID;
6663         }
6664
6665         /* check the level */
6666         switch (r->in.info_ctr->level) {
6667                 case 0:
6668                         return control_printer(r->in.handle, r->in.command, p);
6669                 case 2:
6670                         result = update_printer(p, r->in.handle,
6671                                                 r->in.info_ctr,
6672                                                 r->in.devmode_ctr->devmode);
6673                         if (!W_ERROR_IS_OK(result))
6674                                 return result;
6675                         if (r->in.secdesc_ctr->sd)
6676                                 result = update_printer_sec(r->in.handle, p,
6677                                                             r->in.secdesc_ctr);
6678                         return result;
6679                 case 3:
6680                         return update_printer_sec(r->in.handle, p,
6681                                                   r->in.secdesc_ctr);
6682                 case 7:
6683                         return publish_or_unpublish_printer(p, r->in.handle,
6684                                                             r->in.info_ctr->info.info7);
6685                 case 8:
6686                         return update_printer_devmode(p, r->in.handle,
6687                                                       r->in.devmode_ctr->devmode);
6688                 default:
6689                         return WERR_UNKNOWN_LEVEL;
6690         }
6691 }
6692
6693 /****************************************************************
6694  _spoolss_FindClosePrinterNotify
6695 ****************************************************************/
6696
6697 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
6698                                        struct spoolss_FindClosePrinterNotify *r)
6699 {
6700         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6701
6702         if (!Printer) {
6703                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6704                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6705                 return WERR_BADFID;
6706         }
6707
6708         if (Printer->notify.cli_chan != NULL &&
6709             Printer->notify.cli_chan->active_connections > 0) {
6710                 int snum = -1;
6711
6712                 if (Printer->printer_type == SPLHND_PRINTER) {
6713                         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6714                                 return WERR_BADFID;
6715                         }
6716                 }
6717
6718                 srv_spoolss_replycloseprinter(snum, Printer);
6719         }
6720
6721         Printer->notify.flags=0;
6722         Printer->notify.options=0;
6723         Printer->notify.localmachine[0]='\0';
6724         Printer->notify.printerlocal=0;
6725         TALLOC_FREE(Printer->notify.option);
6726
6727         return WERR_OK;
6728 }
6729
6730 /****************************************************************
6731  _spoolss_AddJob
6732 ****************************************************************/
6733
6734 WERROR _spoolss_AddJob(struct pipes_struct *p,
6735                        struct spoolss_AddJob *r)
6736 {
6737         if (!r->in.buffer && (r->in.offered != 0)) {
6738                 return WERR_INVALID_PARAM;
6739         }
6740
6741         /* this is what a NT server returns for AddJob. AddJob must fail on
6742          * non-local printers */
6743
6744         if (r->in.level != 1) {
6745                 return WERR_UNKNOWN_LEVEL;
6746         }
6747
6748         return WERR_INVALID_PARAM;
6749 }
6750
6751 /****************************************************************************
6752 fill_job_info1
6753 ****************************************************************************/
6754
6755 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6756                              struct spoolss_JobInfo1 *r,
6757                              const print_queue_struct *queue,
6758                              int position, int snum,
6759                              struct spoolss_PrinterInfo2 *pinfo2)
6760 {
6761         struct tm *t;
6762
6763         t = gmtime(&queue->time);
6764
6765         r->job_id               = queue->job;
6766
6767         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6768         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6769         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
6770         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6771         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6772         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6773         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6774         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6775         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6776         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6777         r->text_status          = talloc_strdup(mem_ctx, "");
6778         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6779
6780         r->status               = nt_printj_status(queue->status);
6781         r->priority             = queue->priority;
6782         r->position             = position;
6783         r->total_pages          = queue->page_count;
6784         r->pages_printed        = 0; /* ??? */
6785
6786         init_systemtime(&r->submitted, t);
6787
6788         return WERR_OK;
6789 }
6790
6791 /****************************************************************************
6792 fill_job_info2
6793 ****************************************************************************/
6794
6795 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6796                              struct spoolss_JobInfo2 *r,
6797                              const print_queue_struct *queue,
6798                              int position, int snum,
6799                              struct spoolss_PrinterInfo2 *pinfo2,
6800                              struct spoolss_DeviceMode *devmode)
6801 {
6802         struct tm *t;
6803
6804         t = gmtime(&queue->time);
6805
6806         r->job_id               = queue->job;
6807
6808         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6809         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6810         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
6811         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6812         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6813         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6814         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6815         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6816         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
6817         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6818         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6819         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6820         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
6821         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6822         r->parameters           = talloc_strdup(mem_ctx, "");
6823         W_ERROR_HAVE_NO_MEMORY(r->parameters);
6824         r->driver_name          = talloc_strdup(mem_ctx, pinfo2->drivername);
6825         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6826
6827         r->devmode              = devmode;
6828
6829         r->text_status          = talloc_strdup(mem_ctx, "");
6830         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6831
6832         r->secdesc              = NULL;
6833
6834         r->status               = nt_printj_status(queue->status);
6835         r->priority             = queue->priority;
6836         r->position             = position;
6837         r->start_time           = 0;
6838         r->until_time           = 0;
6839         r->total_pages          = queue->page_count;
6840         r->size                 = queue->size;
6841         init_systemtime(&r->submitted, t);
6842         r->time                 = 0;
6843         r->pages_printed        = 0; /* ??? */
6844
6845         return WERR_OK;
6846 }
6847
6848 /****************************************************************************
6849 fill_job_info3
6850 ****************************************************************************/
6851
6852 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6853                              struct spoolss_JobInfo3 *r,
6854                              const print_queue_struct *queue,
6855                              const print_queue_struct *next_queue,
6856                              int position, int snum,
6857                              struct spoolss_PrinterInfo2 *pinfo2)
6858 {
6859         r->job_id               = queue->job;
6860         r->next_job_id          = 0;
6861         if (next_queue) {
6862                 r->next_job_id  = next_queue->job;
6863         }
6864         r->reserved             = 0;
6865
6866         return WERR_OK;
6867 }
6868
6869 /****************************************************************************
6870  Enumjobs at level 1.
6871 ****************************************************************************/
6872
6873 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6874                               const print_queue_struct *queue,
6875                               uint32_t num_queues, int snum,
6876                               struct spoolss_PrinterInfo2 *pinfo2,
6877                               union spoolss_JobInfo **info_p,
6878                               uint32_t *count)
6879 {
6880         union spoolss_JobInfo *info;
6881         int i;
6882         WERROR result = WERR_OK;
6883
6884         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6885         W_ERROR_HAVE_NO_MEMORY(info);
6886
6887         *count = num_queues;
6888
6889         for (i=0; i<*count; i++) {
6890                 result = fill_job_info1(info,
6891                                         &info[i].info1,
6892                                         &queue[i],
6893                                         i,
6894                                         snum,
6895                                         pinfo2);
6896                 if (!W_ERROR_IS_OK(result)) {
6897                         goto out;
6898                 }
6899         }
6900
6901  out:
6902         if (!W_ERROR_IS_OK(result)) {
6903                 TALLOC_FREE(info);
6904                 *count = 0;
6905                 return result;
6906         }
6907
6908         *info_p = info;
6909
6910         return WERR_OK;
6911 }
6912
6913 /****************************************************************************
6914  Enumjobs at level 2.
6915 ****************************************************************************/
6916
6917 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
6918                               const print_queue_struct *queue,
6919                               uint32_t num_queues, int snum,
6920                               struct spoolss_PrinterInfo2 *pinfo2,
6921                               union spoolss_JobInfo **info_p,
6922                               uint32_t *count)
6923 {
6924         union spoolss_JobInfo *info;
6925         int i;
6926         WERROR result = WERR_OK;
6927
6928         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6929         W_ERROR_HAVE_NO_MEMORY(info);
6930
6931         *count = num_queues;
6932
6933         for (i=0; i<*count; i++) {
6934                 struct spoolss_DeviceMode *devmode;
6935
6936                 result = spoolss_create_default_devmode(info,
6937                                                         pinfo2->printername,
6938                                                         &devmode);
6939                 if (!W_ERROR_IS_OK(result)) {
6940                         DEBUG(3, ("Can't proceed w/o a devmode!"));
6941                         goto out;
6942                 }
6943
6944                 result = fill_job_info2(info,
6945                                         &info[i].info2,
6946                                         &queue[i],
6947                                         i,
6948                                         snum,
6949                                         pinfo2,
6950                                         devmode);
6951                 if (!W_ERROR_IS_OK(result)) {
6952                         goto out;
6953                 }
6954         }
6955
6956  out:
6957         if (!W_ERROR_IS_OK(result)) {
6958                 TALLOC_FREE(info);
6959                 *count = 0;
6960                 return result;
6961         }
6962
6963         *info_p = info;
6964
6965         return WERR_OK;
6966 }
6967
6968 /****************************************************************************
6969  Enumjobs at level 3.
6970 ****************************************************************************/
6971
6972 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
6973                               const print_queue_struct *queue,
6974                               uint32_t num_queues, int snum,
6975                               struct spoolss_PrinterInfo2 *pinfo2,
6976                               union spoolss_JobInfo **info_p,
6977                               uint32_t *count)
6978 {
6979         union spoolss_JobInfo *info;
6980         int i;
6981         WERROR result = WERR_OK;
6982
6983         info = TALLOC_ARRAY(mem_ctx, union spoolss_JobInfo, num_queues);
6984         W_ERROR_HAVE_NO_MEMORY(info);
6985
6986         *count = num_queues;
6987
6988         for (i=0; i<*count; i++) {
6989                 const print_queue_struct *next_queue = NULL;
6990
6991                 if (i+1 < *count) {
6992                         next_queue = &queue[i+1];
6993                 }
6994
6995                 result = fill_job_info3(info,
6996                                         &info[i].info3,
6997                                         &queue[i],
6998                                         next_queue,
6999                                         i,
7000                                         snum,
7001                                         pinfo2);
7002                 if (!W_ERROR_IS_OK(result)) {
7003                         goto out;
7004                 }
7005         }
7006
7007  out:
7008         if (!W_ERROR_IS_OK(result)) {
7009                 TALLOC_FREE(info);
7010                 *count = 0;
7011                 return result;
7012         }
7013
7014         *info_p = info;
7015
7016         return WERR_OK;
7017 }
7018
7019 /****************************************************************
7020  _spoolss_EnumJobs
7021 ****************************************************************/
7022
7023 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7024                          struct spoolss_EnumJobs *r)
7025 {
7026         WERROR result;
7027         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7028         int snum;
7029         print_status_struct prt_status;
7030         print_queue_struct *queue = NULL;
7031         uint32_t count;
7032
7033         /* that's an [in out] buffer */
7034
7035         if (!r->in.buffer && (r->in.offered != 0)) {
7036                 return WERR_INVALID_PARAM;
7037         }
7038
7039         DEBUG(4,("_spoolss_EnumJobs\n"));
7040
7041         *r->out.needed = 0;
7042         *r->out.count = 0;
7043         *r->out.info = NULL;
7044
7045         /* lookup the printer snum and tdb entry */
7046
7047         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7048                 return WERR_BADFID;
7049         }
7050
7051         result = winreg_get_printer(p->mem_ctx,
7052                                     get_session_info_system(),
7053                                     p->msg_ctx,
7054                                     lp_const_servicename(snum),
7055                                     &pinfo2);
7056         if (!W_ERROR_IS_OK(result)) {
7057                 return result;
7058         }
7059
7060         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7061         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7062                 count, prt_status.status, prt_status.message));
7063
7064         if (count == 0) {
7065                 SAFE_FREE(queue);
7066                 TALLOC_FREE(pinfo2);
7067                 return WERR_OK;
7068         }
7069
7070         switch (r->in.level) {
7071         case 1:
7072                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7073                                          pinfo2, r->out.info, r->out.count);
7074                 break;
7075         case 2:
7076                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7077                                          pinfo2, r->out.info, r->out.count);
7078                 break;
7079         case 3:
7080                 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7081                                          pinfo2, r->out.info, r->out.count);
7082                 break;
7083         default:
7084                 result = WERR_UNKNOWN_LEVEL;
7085                 break;
7086         }
7087
7088         SAFE_FREE(queue);
7089         TALLOC_FREE(pinfo2);
7090
7091         if (!W_ERROR_IS_OK(result)) {
7092                 return result;
7093         }
7094
7095         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7096                                                      spoolss_EnumJobs,
7097                                                      *r->out.info, r->in.level,
7098                                                      *r->out.count);
7099         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7100         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7101
7102         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7103 }
7104
7105 /****************************************************************
7106  _spoolss_ScheduleJob
7107 ****************************************************************/
7108
7109 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7110                             struct spoolss_ScheduleJob *r)
7111 {
7112         return WERR_OK;
7113 }
7114
7115 /****************************************************************
7116 ****************************************************************/
7117
7118 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7119                                struct messaging_context *msg_ctx,
7120                                const char *printer_name,
7121                                uint32_t job_id,
7122                                struct spoolss_SetJobInfo1 *r)
7123 {
7124         char *old_doc_name;
7125
7126         if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7127                 return WERR_BADFID;
7128         }
7129
7130         if (strequal(old_doc_name, r->document_name)) {
7131                 return WERR_OK;
7132         }
7133
7134         if (!print_job_set_name(server_event_context(), msg_ctx,
7135                                 printer_name, job_id, r->document_name)) {
7136                 return WERR_BADFID;
7137         }
7138
7139         return WERR_OK;
7140 }
7141
7142 /****************************************************************
7143  _spoolss_SetJob
7144 ****************************************************************/
7145
7146 WERROR _spoolss_SetJob(struct pipes_struct *p,
7147                        struct spoolss_SetJob *r)
7148 {
7149         const struct auth_serversupplied_info *session_info = p->session_info;
7150         int snum;
7151         WERROR errcode = WERR_BADFUNC;
7152
7153         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7154                 return WERR_BADFID;
7155         }
7156
7157         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7158                 return WERR_INVALID_PRINTER_NAME;
7159         }
7160
7161         switch (r->in.command) {
7162         case SPOOLSS_JOB_CONTROL_CANCEL:
7163         case SPOOLSS_JOB_CONTROL_DELETE:
7164                 errcode = print_job_delete(session_info, p->msg_ctx,
7165                                            snum, r->in.job_id);
7166                 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7167                         errcode = WERR_OK;
7168                 }
7169                 break;
7170         case SPOOLSS_JOB_CONTROL_PAUSE:
7171                 if (print_job_pause(session_info, p->msg_ctx,
7172                                     snum, r->in.job_id, &errcode)) {
7173                         errcode = WERR_OK;
7174                 }
7175                 break;
7176         case SPOOLSS_JOB_CONTROL_RESTART:
7177         case SPOOLSS_JOB_CONTROL_RESUME:
7178                 if (print_job_resume(session_info, p->msg_ctx,
7179                                      snum, r->in.job_id, &errcode)) {
7180                         errcode = WERR_OK;
7181                 }
7182                 break;
7183         case 0:
7184                 errcode = WERR_OK;
7185                 break;
7186         default:
7187                 return WERR_UNKNOWN_LEVEL;
7188         }
7189
7190         if (!W_ERROR_IS_OK(errcode)) {
7191                 return errcode;
7192         }
7193
7194         if (r->in.ctr == NULL) {
7195                 return errcode;
7196         }
7197
7198         switch (r->in.ctr->level) {
7199         case 1:
7200                 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7201                                            lp_const_servicename(snum),
7202                                            r->in.job_id,
7203                                            r->in.ctr->info.info1);
7204                 break;
7205         case 2:
7206         case 3:
7207         case 4:
7208         default:
7209                 return WERR_UNKNOWN_LEVEL;
7210         }
7211
7212         return errcode;
7213 }
7214
7215 /****************************************************************************
7216  Enumerates all printer drivers by level and architecture.
7217 ****************************************************************************/
7218
7219 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7220                                                        const struct auth_serversupplied_info *session_info,
7221                                                        struct messaging_context *msg_ctx,
7222                                                        const char *servername,
7223                                                        const char *architecture,
7224                                                        uint32_t level,
7225                                                        union spoolss_DriverInfo **info_p,
7226                                                        uint32_t *count_p)
7227 {
7228         int i;
7229         uint32_t version;
7230         struct spoolss_DriverInfo8 *driver;
7231         union spoolss_DriverInfo *info = NULL;
7232         uint32_t count = 0;
7233         WERROR result = WERR_OK;
7234         uint32_t num_drivers;
7235         const char **drivers;
7236
7237         *count_p = 0;
7238         *info_p = NULL;
7239
7240         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7241                 result = winreg_get_driver_list(mem_ctx, session_info, msg_ctx,
7242                                                 architecture, version,
7243                                                 &num_drivers, &drivers);
7244                 if (!W_ERROR_IS_OK(result)) {
7245                         goto out;
7246                 }
7247                 DEBUG(4, ("we have:[%d] drivers in environment"
7248                           " [%s] and version [%d]\n",
7249                           num_drivers, architecture, version));
7250
7251                 if (num_drivers != 0) {
7252                         info = TALLOC_REALLOC_ARRAY(mem_ctx, info,
7253                                                     union spoolss_DriverInfo,
7254                                                     count + num_drivers);
7255                         if (!info) {
7256                                 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7257                                         "failed to enlarge driver info buffer!\n"));
7258                                 result = WERR_NOMEM;
7259                                 goto out;
7260                         }
7261                 }
7262
7263                 for (i = 0; i < num_drivers; i++) {
7264                         DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7265
7266                         result = winreg_get_driver(mem_ctx, session_info,
7267                                                    msg_ctx,
7268                                                    architecture, drivers[i],
7269                                                    version, &driver);
7270                         if (!W_ERROR_IS_OK(result)) {
7271                                 goto out;
7272                         }
7273
7274                         switch (level) {
7275                         case 1:
7276                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
7277                                                                    driver, servername);
7278                                 break;
7279                         case 2:
7280                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
7281                                                                    driver, servername);
7282                                 break;
7283                         case 3:
7284                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
7285                                                                    driver, servername);
7286                                 break;
7287                         case 4:
7288                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
7289                                                                    driver, servername);
7290                                 break;
7291                         case 5:
7292                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
7293                                                                    driver, servername);
7294                                 break;
7295                         case 6:
7296                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
7297                                                                    driver, servername);
7298                                 break;
7299                         case 8:
7300                                 result = fill_printer_driver_info8(info, &info[count+i].info8,
7301                                                                    driver, servername);
7302                                 break;
7303                         default:
7304                                 result = WERR_UNKNOWN_LEVEL;
7305                                 break;
7306                         }
7307
7308                         TALLOC_FREE(driver);
7309
7310                         if (!W_ERROR_IS_OK(result)) {
7311                                 goto out;
7312                         }
7313                 }
7314
7315                 count += num_drivers;
7316                 TALLOC_FREE(drivers);
7317         }
7318
7319  out:
7320         TALLOC_FREE(drivers);
7321
7322         if (!W_ERROR_IS_OK(result)) {
7323                 TALLOC_FREE(info);
7324                 return result;
7325         }
7326
7327         *info_p = info;
7328         *count_p = count;
7329
7330         return WERR_OK;
7331 }
7332
7333 /****************************************************************************
7334  Enumerates all printer drivers by level.
7335 ****************************************************************************/
7336
7337 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7338                                        const struct auth_serversupplied_info *session_info,
7339                                        struct messaging_context *msg_ctx,
7340                                        const char *servername,
7341                                        const char *architecture,
7342                                        uint32_t level,
7343                                        union spoolss_DriverInfo **info_p,
7344                                        uint32_t *count_p)
7345 {
7346         uint32_t a,i;
7347         WERROR result = WERR_OK;
7348
7349         if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7350
7351                 for (a=0; archi_table[a].long_archi != NULL; a++) {
7352
7353                         union spoolss_DriverInfo *info = NULL;
7354                         uint32_t count = 0;
7355
7356                         result = enumprinterdrivers_level_by_architecture(mem_ctx,
7357                                                                           session_info,
7358                                                                           msg_ctx,
7359                                                                           servername,
7360                                                                           archi_table[a].long_archi,
7361                                                                           level,
7362                                                                           &info,
7363                                                                           &count);
7364                         if (!W_ERROR_IS_OK(result)) {
7365                                 continue;
7366                         }
7367
7368                         for (i=0; i < count; i++) {
7369                                 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7370                                              info[i], info_p, count_p);
7371                         }
7372                 }
7373
7374                 return result;
7375         }
7376
7377         return enumprinterdrivers_level_by_architecture(mem_ctx,
7378                                                         session_info,
7379                                                         msg_ctx,
7380                                                         servername,
7381                                                         architecture,
7382                                                         level,
7383                                                         info_p,
7384                                                         count_p);
7385 }
7386
7387 /****************************************************************
7388  _spoolss_EnumPrinterDrivers
7389 ****************************************************************/
7390
7391 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7392                                    struct spoolss_EnumPrinterDrivers *r)
7393 {
7394         const char *cservername;
7395         WERROR result;
7396
7397         /* that's an [in out] buffer */
7398
7399         if (!r->in.buffer && (r->in.offered != 0)) {
7400                 return WERR_INVALID_PARAM;
7401         }
7402
7403         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7404
7405         *r->out.needed = 0;
7406         *r->out.count = 0;
7407         *r->out.info = NULL;
7408
7409         cservername = canon_servername(r->in.server);
7410
7411         if (!is_myname_or_ipaddr(cservername)) {
7412                 return WERR_UNKNOWN_PRINTER_DRIVER;
7413         }
7414
7415         result = enumprinterdrivers_level(p->mem_ctx,
7416                                           get_session_info_system(),
7417                                           p->msg_ctx,
7418                                           cservername,
7419                                           r->in.environment,
7420                                           r->in.level,
7421                                           r->out.info,
7422                                           r->out.count);
7423         if (!W_ERROR_IS_OK(result)) {
7424                 return result;
7425         }
7426
7427         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7428                                                      spoolss_EnumPrinterDrivers,
7429                                                      *r->out.info, r->in.level,
7430                                                      *r->out.count);
7431         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7432         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7433
7434         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7435 }
7436
7437 /****************************************************************
7438  _spoolss_EnumForms
7439 ****************************************************************/
7440
7441 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7442                           struct spoolss_EnumForms *r)
7443 {
7444         WERROR result;
7445
7446         *r->out.count = 0;
7447         *r->out.needed = 0;
7448         *r->out.info = NULL;
7449
7450         /* that's an [in out] buffer */
7451
7452         if (!r->in.buffer && (r->in.offered != 0) ) {
7453                 return WERR_INVALID_PARAM;
7454         }
7455
7456         DEBUG(4,("_spoolss_EnumForms\n"));
7457         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7458         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7459
7460         switch (r->in.level) {
7461         case 1:
7462                 result = winreg_printer_enumforms1(p->mem_ctx,
7463                                                    get_session_info_system(),
7464                                                    p->msg_ctx,
7465                                                    r->out.count,
7466                                                    r->out.info);
7467                 break;
7468         default:
7469                 result = WERR_UNKNOWN_LEVEL;
7470                 break;
7471         }
7472
7473         if (!W_ERROR_IS_OK(result)) {
7474                 return result;
7475         }
7476
7477         if (*r->out.count == 0) {
7478                 return WERR_NO_MORE_ITEMS;
7479         }
7480
7481         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7482                                                      spoolss_EnumForms,
7483                                                      *r->out.info, r->in.level,
7484                                                      *r->out.count);
7485         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7486         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7487
7488         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7489 }
7490
7491 /****************************************************************
7492  _spoolss_GetForm
7493 ****************************************************************/
7494
7495 WERROR _spoolss_GetForm(struct pipes_struct *p,
7496                         struct spoolss_GetForm *r)
7497 {
7498         WERROR result;
7499
7500         /* that's an [in out] buffer */
7501
7502         if (!r->in.buffer && (r->in.offered != 0)) {
7503                 return WERR_INVALID_PARAM;
7504         }
7505
7506         DEBUG(4,("_spoolss_GetForm\n"));
7507         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7508         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7509
7510         switch (r->in.level) {
7511         case 1:
7512                 result = winreg_printer_getform1(p->mem_ctx,
7513                                                  get_session_info_system(),
7514                                                  p->msg_ctx,
7515                                                  r->in.form_name,
7516                                                  &r->out.info->info1);
7517                 break;
7518         default:
7519                 result = WERR_UNKNOWN_LEVEL;
7520                 break;
7521         }
7522
7523         if (!W_ERROR_IS_OK(result)) {
7524                 TALLOC_FREE(r->out.info);
7525                 return result;
7526         }
7527
7528         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
7529                                                r->out.info, r->in.level);
7530         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7531
7532         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7533 }
7534
7535 /****************************************************************************
7536 ****************************************************************************/
7537
7538 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7539                           struct spoolss_PortInfo1 *r,
7540                           const char *name)
7541 {
7542         r->port_name = talloc_strdup(mem_ctx, name);
7543         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7544
7545         return WERR_OK;
7546 }
7547
7548 /****************************************************************************
7549  TODO: This probably needs distinguish between TCP/IP and Local ports
7550  somehow.
7551 ****************************************************************************/
7552
7553 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7554                           struct spoolss_PortInfo2 *r,
7555                           const char *name)
7556 {
7557         r->port_name = talloc_strdup(mem_ctx, name);
7558         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7559
7560         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7561         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7562
7563         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7564         W_ERROR_HAVE_NO_MEMORY(r->description);
7565
7566         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7567         r->reserved = 0;
7568
7569         return WERR_OK;
7570 }
7571
7572
7573 /****************************************************************************
7574  wrapper around the enumer ports command
7575 ****************************************************************************/
7576
7577 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7578 {
7579         char *cmd = lp_enumports_cmd();
7580         char **qlines = NULL;
7581         char *command = NULL;
7582         int numlines;
7583         int ret;
7584         int fd;
7585
7586         *count = 0;
7587         *lines = NULL;
7588
7589         /* if no hook then just fill in the default port */
7590
7591         if ( !*cmd ) {
7592                 if (!(qlines = TALLOC_ARRAY( NULL, char*, 2 ))) {
7593                         return WERR_NOMEM;
7594                 }
7595                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7596                         TALLOC_FREE(qlines);
7597                         return WERR_NOMEM;
7598                 }
7599                 qlines[1] = NULL;
7600                 numlines = 1;
7601         }
7602         else {
7603                 /* we have a valid enumport command */
7604
7605                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7606                 if (!command) {
7607                         return WERR_NOMEM;
7608                 }
7609
7610                 DEBUG(10,("Running [%s]\n", command));
7611                 ret = smbrun(command, &fd);
7612                 DEBUG(10,("Returned [%d]\n", ret));
7613                 TALLOC_FREE(command);
7614                 if (ret != 0) {
7615                         if (fd != -1) {
7616                                 close(fd);
7617                         }
7618                         return WERR_ACCESS_DENIED;
7619                 }
7620
7621                 numlines = 0;
7622                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7623                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7624                 close(fd);
7625         }
7626
7627         *count = numlines;
7628         *lines = qlines;
7629
7630         return WERR_OK;
7631 }
7632
7633 /****************************************************************************
7634  enumports level 1.
7635 ****************************************************************************/
7636
7637 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7638                                 union spoolss_PortInfo **info_p,
7639                                 uint32_t *count)
7640 {
7641         union spoolss_PortInfo *info = NULL;
7642         int i=0;
7643         WERROR result = WERR_OK;
7644         char **qlines = NULL;
7645         int numlines = 0;
7646
7647         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7648         if (!W_ERROR_IS_OK(result)) {
7649                 goto out;
7650         }
7651
7652         if (numlines) {
7653                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7654                 if (!info) {
7655                         DEBUG(10,("Returning WERR_NOMEM\n"));
7656                         result = WERR_NOMEM;
7657                         goto out;
7658                 }
7659
7660                 for (i=0; i<numlines; i++) {
7661                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7662                         result = fill_port_1(info, &info[i].info1, qlines[i]);
7663                         if (!W_ERROR_IS_OK(result)) {
7664                                 goto out;
7665                         }
7666                 }
7667         }
7668         TALLOC_FREE(qlines);
7669
7670 out:
7671         if (!W_ERROR_IS_OK(result)) {
7672                 TALLOC_FREE(info);
7673                 TALLOC_FREE(qlines);
7674                 *count = 0;
7675                 *info_p = NULL;
7676                 return result;
7677         }
7678
7679         *info_p = info;
7680         *count = numlines;
7681
7682         return WERR_OK;
7683 }
7684
7685 /****************************************************************************
7686  enumports level 2.
7687 ****************************************************************************/
7688
7689 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7690                                 union spoolss_PortInfo **info_p,
7691                                 uint32_t *count)
7692 {
7693         union spoolss_PortInfo *info = NULL;
7694         int i=0;
7695         WERROR result = WERR_OK;
7696         char **qlines = NULL;
7697         int numlines = 0;
7698
7699         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7700         if (!W_ERROR_IS_OK(result)) {
7701                 goto out;
7702         }
7703
7704         if (numlines) {
7705                 info = TALLOC_ARRAY(mem_ctx, union spoolss_PortInfo, numlines);
7706                 if (!info) {
7707                         DEBUG(10,("Returning WERR_NOMEM\n"));
7708                         result = WERR_NOMEM;
7709                         goto out;
7710                 }
7711
7712                 for (i=0; i<numlines; i++) {
7713                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7714                         result = fill_port_2(info, &info[i].info2, qlines[i]);
7715                         if (!W_ERROR_IS_OK(result)) {
7716                                 goto out;
7717                         }
7718                 }
7719         }
7720         TALLOC_FREE(qlines);
7721
7722 out:
7723         if (!W_ERROR_IS_OK(result)) {
7724                 TALLOC_FREE(info);
7725                 TALLOC_FREE(qlines);
7726                 *count = 0;
7727                 *info_p = NULL;
7728                 return result;
7729         }
7730
7731         *info_p = info;
7732         *count = numlines;
7733
7734         return WERR_OK;
7735 }
7736
7737 /****************************************************************
7738  _spoolss_EnumPorts
7739 ****************************************************************/
7740
7741 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
7742                           struct spoolss_EnumPorts *r)
7743 {
7744         WERROR result;
7745
7746         /* that's an [in out] buffer */
7747
7748         if (!r->in.buffer && (r->in.offered != 0)) {
7749                 return WERR_INVALID_PARAM;
7750         }
7751
7752         DEBUG(4,("_spoolss_EnumPorts\n"));
7753
7754         *r->out.count = 0;
7755         *r->out.needed = 0;
7756         *r->out.info = NULL;
7757
7758         switch (r->in.level) {
7759         case 1:
7760                 result = enumports_level_1(p->mem_ctx, r->out.info,
7761                                            r->out.count);
7762                 break;
7763         case 2:
7764                 result = enumports_level_2(p->mem_ctx, r->out.info,
7765                                            r->out.count);
7766                 break;
7767         default:
7768                 return WERR_UNKNOWN_LEVEL;
7769         }
7770
7771         if (!W_ERROR_IS_OK(result)) {
7772                 return result;
7773         }
7774
7775         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7776                                                      spoolss_EnumPorts,
7777                                                      *r->out.info, r->in.level,
7778                                                      *r->out.count);
7779         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7780         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7781
7782         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7783 }
7784
7785 /****************************************************************************
7786 ****************************************************************************/
7787
7788 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
7789                                            const char *server,
7790                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
7791                                            struct spoolss_DeviceMode *devmode,
7792                                            struct security_descriptor *secdesc,
7793                                            struct spoolss_UserLevelCtr *user_ctr,
7794                                            struct policy_handle *handle)
7795 {
7796         struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
7797         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
7798         int     snum;
7799         WERROR err = WERR_OK;
7800
7801         /* samba does not have a concept of local, non-shared printers yet, so
7802          * make sure we always setup sharename - gd */
7803         if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
7804             (info2->printername != NULL && info2->printername[0] != '\0')) {
7805                 DEBUG(5, ("spoolss_addprinterex_level_2: "
7806                         "no sharename has been set, setting printername %s as sharename\n",
7807                         info2->printername));
7808                 info2->sharename = info2->printername;
7809         }
7810
7811         /* check to see if the printer already exists */
7812         if ((snum = print_queue_snum(info2->sharename)) != -1) {
7813                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7814                         info2->sharename));
7815                 return WERR_PRINTER_ALREADY_EXISTS;
7816         }
7817
7818         if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7819                 if ((snum = print_queue_snum(info2->printername)) != -1) {
7820                         DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7821                                 info2->printername));
7822                         return WERR_PRINTER_ALREADY_EXISTS;
7823                 }
7824         }
7825
7826         /* validate printer info struct */
7827         if (!info2->printername || strlen(info2->printername) == 0) {
7828                 return WERR_INVALID_PRINTER_NAME;
7829         }
7830         if (!info2->portname || strlen(info2->portname) == 0) {
7831                 return WERR_UNKNOWN_PORT;
7832         }
7833         if (!info2->drivername || strlen(info2->drivername) == 0) {
7834                 return WERR_UNKNOWN_PRINTER_DRIVER;
7835         }
7836         if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
7837                 return WERR_UNKNOWN_PRINTPROCESSOR;
7838         }
7839
7840         /* FIXME!!!  smbd should check to see if the driver is installed before
7841            trying to add a printer like this  --jerry */
7842
7843         if (*lp_addprinter_cmd() ) {
7844                 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
7845                                        info2, p->client_id->addr,
7846                                        p->msg_ctx) ) {
7847                         return WERR_ACCESS_DENIED;
7848                 }
7849         } else {
7850                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7851                         "smb.conf parameter \"addprinter command\" is defined. This"
7852                         "parameter must exist for this call to succeed\n",
7853                         info2->sharename ));
7854         }
7855
7856         if ((snum = print_queue_snum(info2->sharename)) == -1) {
7857                 return WERR_ACCESS_DENIED;
7858         }
7859
7860         /* you must be a printer admin to add a new printer */
7861         if (!print_access_check(p->session_info,
7862                                 p->msg_ctx,
7863                                 snum,
7864                                 PRINTER_ACCESS_ADMINISTER)) {
7865                 return WERR_ACCESS_DENIED;
7866         }
7867
7868         /*
7869          * Do sanity check on the requested changes for Samba.
7870          */
7871
7872         if (!check_printer_ok(p->mem_ctx, info2, snum)) {
7873                 return WERR_INVALID_PARAM;
7874         }
7875
7876         if (devmode == NULL) {
7877                 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
7878         }
7879
7880         update_dsspooler(p->mem_ctx,
7881                          get_session_info_system(),
7882                          p->msg_ctx,
7883                          0,
7884                          info2,
7885                          NULL);
7886
7887         err = winreg_update_printer(p->mem_ctx,
7888                                     get_session_info_system(),
7889                                     p->msg_ctx,
7890                                     info2->sharename,
7891                                     info2_mask,
7892                                     info2,
7893                                     devmode,
7894                                     secdesc);
7895         if (!W_ERROR_IS_OK(err)) {
7896                 return err;
7897         }
7898
7899         err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
7900         if (!W_ERROR_IS_OK(err)) {
7901                 /* Handle open failed - remove addition. */
7902                 ZERO_STRUCTP(handle);
7903                 return err;
7904         }
7905
7906         return WERR_OK;
7907 }
7908
7909 /****************************************************************
7910  _spoolss_AddPrinterEx
7911 ****************************************************************/
7912
7913 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
7914                              struct spoolss_AddPrinterEx *r)
7915 {
7916         switch (r->in.info_ctr->level) {
7917         case 1:
7918                 /* we don't handle yet */
7919                 /* but I know what to do ... */
7920                 return WERR_UNKNOWN_LEVEL;
7921         case 2:
7922                 return spoolss_addprinterex_level_2(p, r->in.server,
7923                                                     r->in.info_ctr,
7924                                                     r->in.devmode_ctr->devmode,
7925                                                     r->in.secdesc_ctr->sd,
7926                                                     r->in.userlevel_ctr,
7927                                                     r->out.handle);
7928         default:
7929                 return WERR_UNKNOWN_LEVEL;
7930         }
7931 }
7932
7933 /****************************************************************
7934  _spoolss_AddPrinter
7935 ****************************************************************/
7936
7937 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
7938                            struct spoolss_AddPrinter *r)
7939 {
7940         struct spoolss_AddPrinterEx a;
7941         struct spoolss_UserLevelCtr userlevel_ctr;
7942
7943         ZERO_STRUCT(userlevel_ctr);
7944
7945         userlevel_ctr.level = 1;
7946
7947         a.in.server             = r->in.server;
7948         a.in.info_ctr           = r->in.info_ctr;
7949         a.in.devmode_ctr        = r->in.devmode_ctr;
7950         a.in.secdesc_ctr        = r->in.secdesc_ctr;
7951         a.in.userlevel_ctr      = &userlevel_ctr;
7952         a.out.handle            = r->out.handle;
7953
7954         return _spoolss_AddPrinterEx(p, &a);
7955 }
7956
7957 /****************************************************************
7958  _spoolss_AddPrinterDriverEx
7959 ****************************************************************/
7960
7961 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
7962                                    struct spoolss_AddPrinterDriverEx *r)
7963 {
7964         WERROR err = WERR_OK;
7965         const char *driver_name = NULL;
7966         uint32_t version;
7967         const char *fn;
7968
7969         switch (p->opnum) {
7970                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
7971                         fn = "_spoolss_AddPrinterDriver";
7972                         break;
7973                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
7974                         fn = "_spoolss_AddPrinterDriverEx";
7975                         break;
7976                 default:
7977                         return WERR_INVALID_PARAM;
7978         }
7979
7980         /*
7981          * we only support the semantics of AddPrinterDriver()
7982          * i.e. only copy files that are newer than existing ones
7983          */
7984
7985         if (r->in.flags == 0) {
7986                 return WERR_INVALID_PARAM;
7987         }
7988
7989         if (r->in.flags != APD_COPY_NEW_FILES) {
7990                 return WERR_ACCESS_DENIED;
7991         }
7992
7993         /* FIXME */
7994         if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
7995                 /* Clever hack from Martin Zielinski <mz@seh.de>
7996                  * to allow downgrade from level 8 (Vista).
7997                  */
7998                 DEBUG(0,("%s: level %d not yet implemented\n", fn,
7999                         r->in.info_ctr->level));
8000                 return WERR_UNKNOWN_LEVEL;
8001         }
8002
8003         DEBUG(5,("Cleaning driver's information\n"));
8004         err = clean_up_driver_struct(p->mem_ctx, p, r->in.info_ctr);
8005         if (!W_ERROR_IS_OK(err))
8006                 goto done;
8007
8008         DEBUG(5,("Moving driver to final destination\n"));
8009         err = move_driver_to_download_area(p, r->in.info_ctr);
8010         if (!W_ERROR_IS_OK(err)) {
8011                 goto done;
8012         }
8013
8014         err = winreg_add_driver(p->mem_ctx,
8015                                 get_session_info_system(),
8016                                 p->msg_ctx,
8017                                 r->in.info_ctr,
8018                                 &driver_name,
8019                                 &version);
8020         if (!W_ERROR_IS_OK(err)) {
8021                 goto done;
8022         }
8023
8024         /*
8025          * I think this is where he DrvUpgradePrinter() hook would be
8026          * be called in a driver's interface DLL on a Windows NT 4.0/2k
8027          * server.  Right now, we just need to send ourselves a message
8028          * to update each printer bound to this driver.   --jerry
8029          */
8030
8031         if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8032                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8033                         fn, driver_name));
8034         }
8035
8036 done:
8037         return err;
8038 }
8039
8040 /****************************************************************
8041  _spoolss_AddPrinterDriver
8042 ****************************************************************/
8043
8044 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8045                                  struct spoolss_AddPrinterDriver *r)
8046 {
8047         struct spoolss_AddPrinterDriverEx a;
8048
8049         switch (r->in.info_ctr->level) {
8050         case 2:
8051         case 3:
8052         case 4:
8053         case 5:
8054                 break;
8055         default:
8056                 return WERR_UNKNOWN_LEVEL;
8057         }
8058
8059         a.in.servername         = r->in.servername;
8060         a.in.info_ctr           = r->in.info_ctr;
8061         a.in.flags              = APD_COPY_NEW_FILES;
8062
8063         return _spoolss_AddPrinterDriverEx(p, &a);
8064 }
8065
8066 /****************************************************************************
8067 ****************************************************************************/
8068
8069 struct _spoolss_paths {
8070         int type;
8071         const char *share;
8072         const char *dir;
8073 };
8074
8075 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8076
8077 static const struct _spoolss_paths spoolss_paths[]= {
8078         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
8079         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
8080 };
8081
8082 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8083                                           const char *servername,
8084                                           const char *environment,
8085                                           int component,
8086                                           char **path)
8087 {
8088         const char *pservername = NULL;
8089         const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
8090         const char *short_archi;
8091
8092         *path = NULL;
8093
8094         /* environment may be empty */
8095         if (environment && strlen(environment)) {
8096                 long_archi = environment;
8097         }
8098
8099         /* servername may be empty */
8100         if (servername && strlen(servername)) {
8101                 pservername = canon_servername(servername);
8102
8103                 if (!is_myname_or_ipaddr(pservername)) {
8104                         return WERR_INVALID_PARAM;
8105                 }
8106         }
8107
8108         if (!(short_archi = get_short_archi(long_archi))) {
8109                 return WERR_INVALID_ENVIRONMENT;
8110         }
8111
8112         switch (component) {
8113         case SPOOLSS_PRTPROCS_PATH:
8114         case SPOOLSS_DRIVER_PATH:
8115                 if (pservername) {
8116                         *path = talloc_asprintf(mem_ctx,
8117                                         "\\\\%s\\%s\\%s",
8118                                         pservername,
8119                                         spoolss_paths[component].share,
8120                                         short_archi);
8121                 } else {
8122                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8123                                         SPOOLSS_DEFAULT_SERVER_PATH,
8124                                         spoolss_paths[component].dir,
8125                                         short_archi);
8126                 }
8127                 break;
8128         default:
8129                 return WERR_INVALID_PARAM;
8130         }
8131
8132         if (!*path) {
8133                 return WERR_NOMEM;
8134         }
8135
8136         return WERR_OK;
8137 }
8138
8139 /****************************************************************************
8140 ****************************************************************************/
8141
8142 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8143                                           const char *servername,
8144                                           const char *environment,
8145                                           struct spoolss_DriverDirectoryInfo1 *r)
8146 {
8147         WERROR werr;
8148         char *path = NULL;
8149
8150         werr = compose_spoolss_server_path(mem_ctx,
8151                                            servername,
8152                                            environment,
8153                                            SPOOLSS_DRIVER_PATH,
8154                                            &path);
8155         if (!W_ERROR_IS_OK(werr)) {
8156                 return werr;
8157         }
8158
8159         DEBUG(4,("printer driver directory: [%s]\n", path));
8160
8161         r->directory_name = path;
8162
8163         return WERR_OK;
8164 }
8165
8166 /****************************************************************
8167  _spoolss_GetPrinterDriverDirectory
8168 ****************************************************************/
8169
8170 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8171                                           struct spoolss_GetPrinterDriverDirectory *r)
8172 {
8173         WERROR werror;
8174
8175         /* that's an [in out] buffer */
8176
8177         if (!r->in.buffer && (r->in.offered != 0)) {
8178                 return WERR_INVALID_PARAM;
8179         }
8180
8181         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8182                 r->in.level));
8183
8184         *r->out.needed = 0;
8185
8186         /* r->in.level is ignored */
8187
8188         werror = getprinterdriverdir_level_1(p->mem_ctx,
8189                                              r->in.server,
8190                                              r->in.environment,
8191                                              &r->out.info->info1);
8192         if (!W_ERROR_IS_OK(werror)) {
8193                 TALLOC_FREE(r->out.info);
8194                 return werror;
8195         }
8196
8197         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8198                                                r->out.info, r->in.level);
8199         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8200
8201         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8202 }
8203
8204 /****************************************************************
8205  _spoolss_EnumPrinterData
8206 ****************************************************************/
8207
8208 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8209                                 struct spoolss_EnumPrinterData *r)
8210 {
8211         WERROR result;
8212         struct spoolss_EnumPrinterDataEx r2;
8213         uint32_t count;
8214         struct spoolss_PrinterEnumValues *info, *val = NULL;
8215         uint32_t needed;
8216
8217         r2.in.handle    = r->in.handle;
8218         r2.in.key_name  = "PrinterDriverData";
8219         r2.in.offered   = 0;
8220         r2.out.count    = &count;
8221         r2.out.info     = &info;
8222         r2.out.needed   = &needed;
8223
8224         result = _spoolss_EnumPrinterDataEx(p, &r2);
8225         if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8226                 r2.in.offered = needed;
8227                 result = _spoolss_EnumPrinterDataEx(p, &r2);
8228         }
8229         if (!W_ERROR_IS_OK(result)) {
8230                 return result;
8231         }
8232
8233         /*
8234          * The NT machine wants to know the biggest size of value and data
8235          *
8236          * cf: MSDN EnumPrinterData remark section
8237          */
8238
8239         if (!r->in.value_offered && !r->in.data_offered) {
8240                 uint32_t biggest_valuesize = 0;
8241                 uint32_t biggest_datasize = 0;
8242                 int i, name_length;
8243
8244                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8245
8246                 for (i=0; i<count; i++) {
8247
8248                         name_length = strlen(info[i].value_name);
8249                         if (strlen(info[i].value_name) > biggest_valuesize) {
8250                                 biggest_valuesize = name_length;
8251                         }
8252
8253                         if (info[i].data_length > biggest_datasize) {
8254                                 biggest_datasize = info[i].data_length;
8255                         }
8256
8257                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8258                                 biggest_datasize));
8259                 }
8260
8261                 /* the value is an UNICODE string but real_value_size is the length
8262                    in bytes including the trailing 0 */
8263
8264                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8265                 *r->out.data_needed  = biggest_datasize;
8266
8267                 DEBUG(6,("final values: [%d], [%d]\n",
8268                         *r->out.value_needed, *r->out.data_needed));
8269
8270                 return WERR_OK;
8271         }
8272
8273         if (r->in.enum_index < count) {
8274                 val = &info[r->in.enum_index];
8275         }
8276
8277         if (val == NULL) {
8278                 /* out_value should default to "" or else NT4 has
8279                    problems unmarshalling the response */
8280
8281                 if (r->in.value_offered) {
8282                         *r->out.value_needed = 1;
8283                         r->out.value_name = talloc_strdup(r, "");
8284                         if (!r->out.value_name) {
8285                                 return WERR_NOMEM;
8286                         }
8287                 } else {
8288                         r->out.value_name = NULL;
8289                         *r->out.value_needed = 0;
8290                 }
8291
8292                 /* the data is counted in bytes */
8293
8294                 *r->out.data_needed = r->in.data_offered;
8295
8296                 result = WERR_NO_MORE_ITEMS;
8297         } else {
8298                 /*
8299                  * the value is:
8300                  * - counted in bytes in the request
8301                  * - counted in UNICODE chars in the max reply
8302                  * - counted in bytes in the real size
8303                  *
8304                  * take a pause *before* coding not *during* coding
8305                  */
8306
8307                 /* name */
8308                 if (r->in.value_offered) {
8309                         r->out.value_name = talloc_strdup(r, val->value_name);
8310                         if (!r->out.value_name) {
8311                                 return WERR_NOMEM;
8312                         }
8313                         *r->out.value_needed = val->value_name_len;
8314                 } else {
8315                         r->out.value_name = NULL;
8316                         *r->out.value_needed = 0;
8317                 }
8318
8319                 /* type */
8320
8321                 *r->out.type = val->type;
8322
8323                 /* data - counted in bytes */
8324
8325                 /*
8326                  * See the section "Dynamically Typed Query Parameters"
8327                  * in MS-RPRN.
8328                  */
8329
8330                 if (r->out.data && val->data && val->data->data &&
8331                                 val->data_length && r->in.data_offered) {
8332                         memcpy(r->out.data, val->data->data,
8333                                 MIN(val->data_length,r->in.data_offered));
8334                 }
8335
8336                 *r->out.data_needed = val->data_length;
8337
8338                 result = WERR_OK;
8339         }
8340
8341         return result;
8342 }
8343
8344 /****************************************************************
8345  _spoolss_SetPrinterData
8346 ****************************************************************/
8347
8348 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8349                                struct spoolss_SetPrinterData *r)
8350 {
8351         struct spoolss_SetPrinterDataEx r2;
8352
8353         r2.in.handle            = r->in.handle;
8354         r2.in.key_name          = "PrinterDriverData";
8355         r2.in.value_name        = r->in.value_name;
8356         r2.in.type              = r->in.type;
8357         r2.in.data              = r->in.data;
8358         r2.in.offered           = r->in.offered;
8359
8360         return _spoolss_SetPrinterDataEx(p, &r2);
8361 }
8362
8363 /****************************************************************
8364  _spoolss_ResetPrinter
8365 ****************************************************************/
8366
8367 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8368                              struct spoolss_ResetPrinter *r)
8369 {
8370         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8371         int             snum;
8372
8373         DEBUG(5,("_spoolss_ResetPrinter\n"));
8374
8375         /*
8376          * All we do is to check to see if the handle and queue is valid.
8377          * This call really doesn't mean anything to us because we only
8378          * support RAW printing.   --jerry
8379          */
8380
8381         if (!Printer) {
8382                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8383                         OUR_HANDLE(r->in.handle)));
8384                 return WERR_BADFID;
8385         }
8386
8387         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8388                 return WERR_BADFID;
8389
8390
8391         /* blindly return success */
8392         return WERR_OK;
8393 }
8394
8395 /****************************************************************
8396  _spoolss_DeletePrinterData
8397 ****************************************************************/
8398
8399 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8400                                   struct spoolss_DeletePrinterData *r)
8401 {
8402         struct spoolss_DeletePrinterDataEx r2;
8403
8404         r2.in.handle            = r->in.handle;
8405         r2.in.key_name          = "PrinterDriverData";
8406         r2.in.value_name        = r->in.value_name;
8407
8408         return _spoolss_DeletePrinterDataEx(p, &r2);
8409 }
8410
8411 /****************************************************************
8412  _spoolss_AddForm
8413 ****************************************************************/
8414
8415 WERROR _spoolss_AddForm(struct pipes_struct *p,
8416                         struct spoolss_AddForm *r)
8417 {
8418         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8419         int snum = -1;
8420         WERROR status = WERR_OK;
8421
8422         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8423
8424         DEBUG(5,("_spoolss_AddForm\n"));
8425
8426         if (!Printer) {
8427                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8428                         OUR_HANDLE(r->in.handle)));
8429                 return WERR_BADFID;
8430         }
8431
8432         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8433            and not a printer admin, then fail */
8434
8435         if ((p->session_info->utok.uid != sec_initial_uid()) &&
8436             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8437             !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8438                                           p->session_info->info3->base.domain.string,
8439                                           NULL,
8440                                           p->session_info->security_token,
8441                                           lp_printer_admin(snum))) {
8442                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8443                 return WERR_ACCESS_DENIED;
8444         }
8445
8446         switch (form->flags) {
8447         case SPOOLSS_FORM_USER:
8448         case SPOOLSS_FORM_BUILTIN:
8449         case SPOOLSS_FORM_PRINTER:
8450                 break;
8451         default:
8452                 return WERR_INVALID_PARAM;
8453         }
8454
8455         status = winreg_printer_addform1(p->mem_ctx,
8456                                          get_session_info_system(),
8457                                          p->msg_ctx,
8458                                          form);
8459         if (!W_ERROR_IS_OK(status)) {
8460                 return status;
8461         }
8462
8463         /*
8464          * ChangeID must always be set if this is a printer
8465          */
8466         if (Printer->printer_type == SPLHND_PRINTER) {
8467                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8468                         return WERR_BADFID;
8469                 }
8470
8471                 status = winreg_printer_update_changeid(p->mem_ctx,
8472                                                         get_session_info_system(),
8473                                                         p->msg_ctx,
8474                                                         lp_const_servicename(snum));
8475                 if (!W_ERROR_IS_OK(status)) {
8476                         return status;
8477                 }
8478         }
8479
8480         return status;
8481 }
8482
8483 /****************************************************************
8484  _spoolss_DeleteForm
8485 ****************************************************************/
8486
8487 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8488                            struct spoolss_DeleteForm *r)
8489 {
8490         const char *form_name = r->in.form_name;
8491         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8492         int snum = -1;
8493         WERROR status = WERR_OK;
8494
8495         DEBUG(5,("_spoolss_DeleteForm\n"));
8496
8497         if (!Printer) {
8498                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8499                         OUR_HANDLE(r->in.handle)));
8500                 return WERR_BADFID;
8501         }
8502
8503         if ((p->session_info->utok.uid != sec_initial_uid()) &&
8504             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8505             !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8506                                           p->session_info->info3->base.domain.string,
8507                                           NULL,
8508                                           p->session_info->security_token,
8509                                           lp_printer_admin(snum))) {
8510                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8511                 return WERR_ACCESS_DENIED;
8512         }
8513
8514         status = winreg_printer_deleteform1(p->mem_ctx,
8515                                             get_session_info_system(),
8516                                             p->msg_ctx,
8517                                             form_name);
8518         if (!W_ERROR_IS_OK(status)) {
8519                 return status;
8520         }
8521
8522         /*
8523          * ChangeID must always be set if this is a printer
8524          */
8525         if (Printer->printer_type == SPLHND_PRINTER) {
8526                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8527                         return WERR_BADFID;
8528                 }
8529
8530                 status = winreg_printer_update_changeid(p->mem_ctx,
8531                                                         get_session_info_system(),
8532                                                         p->msg_ctx,
8533                                                         lp_const_servicename(snum));
8534                 if (!W_ERROR_IS_OK(status)) {
8535                         return status;
8536                 }
8537         }
8538
8539         return status;
8540 }
8541
8542 /****************************************************************
8543  _spoolss_SetForm
8544 ****************************************************************/
8545
8546 WERROR _spoolss_SetForm(struct pipes_struct *p,
8547                         struct spoolss_SetForm *r)
8548 {
8549         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8550         const char *form_name = r->in.form_name;
8551         int snum = -1;
8552         WERROR status = WERR_OK;
8553
8554         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8555
8556         DEBUG(5,("_spoolss_SetForm\n"));
8557
8558         if (!Printer) {
8559                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8560                         OUR_HANDLE(r->in.handle)));
8561                 return WERR_BADFID;
8562         }
8563
8564         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8565            and not a printer admin, then fail */
8566
8567         if ((p->session_info->utok.uid != sec_initial_uid()) &&
8568              !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8569              !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8570                                           p->session_info->info3->base.domain.string,
8571                                           NULL,
8572                                           p->session_info->security_token,
8573                                           lp_printer_admin(snum))) {
8574                 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8575                 return WERR_ACCESS_DENIED;
8576         }
8577
8578         status = winreg_printer_setform1(p->mem_ctx,
8579                                          get_session_info_system(),
8580                                          p->msg_ctx,
8581                                          form_name,
8582                                          form);
8583         if (!W_ERROR_IS_OK(status)) {
8584                 return status;
8585         }
8586
8587         /*
8588          * ChangeID must always be set if this is a printer
8589          */
8590         if (Printer->printer_type == SPLHND_PRINTER) {
8591                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8592                         return WERR_BADFID;
8593                 }
8594
8595                 status = winreg_printer_update_changeid(p->mem_ctx,
8596                                                         get_session_info_system(),
8597                                                         p->msg_ctx,
8598                                                         lp_const_servicename(snum));
8599                 if (!W_ERROR_IS_OK(status)) {
8600                         return status;
8601                 }
8602         }
8603
8604         return status;
8605 }
8606
8607 /****************************************************************************
8608  fill_print_processor1
8609 ****************************************************************************/
8610
8611 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8612                                     struct spoolss_PrintProcessorInfo1 *r,
8613                                     const char *print_processor_name)
8614 {
8615         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8616         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8617
8618         return WERR_OK;
8619 }
8620
8621 /****************************************************************************
8622  enumprintprocessors level 1.
8623 ****************************************************************************/
8624
8625 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8626                                           union spoolss_PrintProcessorInfo **info_p,
8627                                           uint32_t *count)
8628 {
8629         union spoolss_PrintProcessorInfo *info;
8630         WERROR result;
8631
8632         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8633         W_ERROR_HAVE_NO_MEMORY(info);
8634
8635         *count = 1;
8636
8637         result = fill_print_processor1(info, &info[0].info1, "winprint");
8638         if (!W_ERROR_IS_OK(result)) {
8639                 goto out;
8640         }
8641
8642  out:
8643         if (!W_ERROR_IS_OK(result)) {
8644                 TALLOC_FREE(info);
8645                 *count = 0;
8646                 return result;
8647         }
8648
8649         *info_p = info;
8650
8651         return WERR_OK;
8652 }
8653
8654 /****************************************************************
8655  _spoolss_EnumPrintProcessors
8656 ****************************************************************/
8657
8658 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
8659                                     struct spoolss_EnumPrintProcessors *r)
8660 {
8661         WERROR result;
8662
8663         /* that's an [in out] buffer */
8664
8665         if (!r->in.buffer && (r->in.offered != 0)) {
8666                 return WERR_INVALID_PARAM;
8667         }
8668
8669         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8670
8671         /*
8672          * Enumerate the print processors ...
8673          *
8674          * Just reply with "winprint", to keep NT happy
8675          * and I can use my nice printer checker.
8676          */
8677
8678         *r->out.count = 0;
8679         *r->out.needed = 0;
8680         *r->out.info = NULL;
8681
8682         if (!get_short_archi(r->in.environment)) {
8683                 return WERR_INVALID_ENVIRONMENT;
8684         }
8685
8686         switch (r->in.level) {
8687         case 1:
8688                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8689                                                      r->out.count);
8690                 break;
8691         default:
8692                 return WERR_UNKNOWN_LEVEL;
8693         }
8694
8695         if (!W_ERROR_IS_OK(result)) {
8696                 return result;
8697         }
8698
8699         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8700                                                      spoolss_EnumPrintProcessors,
8701                                                      *r->out.info, r->in.level,
8702                                                      *r->out.count);
8703         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8704         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8705
8706         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8707 }
8708
8709 /****************************************************************************
8710  fill_printprocdatatype1
8711 ****************************************************************************/
8712
8713 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8714                                       struct spoolss_PrintProcDataTypesInfo1 *r,
8715                                       const char *name_array)
8716 {
8717         r->name_array = talloc_strdup(mem_ctx, name_array);
8718         W_ERROR_HAVE_NO_MEMORY(r->name_array);
8719
8720         return WERR_OK;
8721 }
8722
8723 /****************************************************************************
8724  enumprintprocdatatypes level 1.
8725 ****************************************************************************/
8726
8727 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8728                                              union spoolss_PrintProcDataTypesInfo **info_p,
8729                                              uint32_t *count)
8730 {
8731         WERROR result;
8732         union spoolss_PrintProcDataTypesInfo *info;
8733
8734         info = TALLOC_ARRAY(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8735         W_ERROR_HAVE_NO_MEMORY(info);
8736
8737         *count = 1;
8738
8739         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8740         if (!W_ERROR_IS_OK(result)) {
8741                 goto out;
8742         }
8743
8744  out:
8745         if (!W_ERROR_IS_OK(result)) {
8746                 TALLOC_FREE(info);
8747                 *count = 0;
8748                 return result;
8749         }
8750
8751         *info_p = info;
8752
8753         return WERR_OK;
8754 }
8755
8756 /****************************************************************
8757  _spoolss_EnumPrintProcDataTypes
8758 ****************************************************************/
8759
8760 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
8761                                        struct spoolss_EnumPrintProcDataTypes *r)
8762 {
8763         WERROR result;
8764
8765         /* that's an [in out] buffer */
8766
8767         if (!r->in.buffer && (r->in.offered != 0)) {
8768                 return WERR_INVALID_PARAM;
8769         }
8770
8771         DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8772
8773         *r->out.count = 0;
8774         *r->out.needed = 0;
8775         *r->out.info = NULL;
8776
8777         if (r->in.print_processor_name == NULL ||
8778             !strequal(r->in.print_processor_name, "winprint")) {
8779                 return WERR_UNKNOWN_PRINTPROCESSOR;
8780         }
8781
8782         switch (r->in.level) {
8783         case 1:
8784                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8785                                                         r->out.count);
8786                 break;
8787         default:
8788                 return WERR_UNKNOWN_LEVEL;
8789         }
8790
8791         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8792                                                      spoolss_EnumPrintProcDataTypes,
8793                                                      *r->out.info, r->in.level,
8794                                                      *r->out.count);
8795         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8796         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8797
8798         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8799 }
8800
8801 /****************************************************************************
8802  fill_monitor_1
8803 ****************************************************************************/
8804
8805 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8806                              struct spoolss_MonitorInfo1 *r,
8807                              const char *monitor_name)
8808 {
8809         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8810         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8811
8812         return WERR_OK;
8813 }
8814
8815 /****************************************************************************
8816  fill_monitor_2
8817 ****************************************************************************/
8818
8819 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8820                              struct spoolss_MonitorInfo2 *r,
8821                              const char *monitor_name,
8822                              const char *environment,
8823                              const char *dll_name)
8824 {
8825         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8826         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8827         r->environment                  = talloc_strdup(mem_ctx, environment);
8828         W_ERROR_HAVE_NO_MEMORY(r->environment);
8829         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
8830         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8831
8832         return WERR_OK;
8833 }
8834
8835 /****************************************************************************
8836  enumprintmonitors level 1.
8837 ****************************************************************************/
8838
8839 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8840                                         union spoolss_MonitorInfo **info_p,
8841                                         uint32_t *count)
8842 {
8843         union spoolss_MonitorInfo *info;
8844         WERROR result = WERR_OK;
8845
8846         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8847         W_ERROR_HAVE_NO_MEMORY(info);
8848
8849         *count = 2;
8850
8851         result = fill_monitor_1(info, &info[0].info1,
8852                                 SPL_LOCAL_PORT);
8853         if (!W_ERROR_IS_OK(result)) {
8854                 goto out;
8855         }
8856
8857         result = fill_monitor_1(info, &info[1].info1,
8858                                 SPL_TCPIP_PORT);
8859         if (!W_ERROR_IS_OK(result)) {
8860                 goto out;
8861         }
8862
8863 out:
8864         if (!W_ERROR_IS_OK(result)) {
8865                 TALLOC_FREE(info);
8866                 *count = 0;
8867                 return result;
8868         }
8869
8870         *info_p = info;
8871
8872         return WERR_OK;
8873 }
8874
8875 /****************************************************************************
8876  enumprintmonitors level 2.
8877 ****************************************************************************/
8878
8879 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
8880                                         union spoolss_MonitorInfo **info_p,
8881                                         uint32_t *count)
8882 {
8883         union spoolss_MonitorInfo *info;
8884         WERROR result = WERR_OK;
8885
8886         info = TALLOC_ARRAY(mem_ctx, union spoolss_MonitorInfo, 2);
8887         W_ERROR_HAVE_NO_MEMORY(info);
8888
8889         *count = 2;
8890
8891         result = fill_monitor_2(info, &info[0].info2,
8892                                 SPL_LOCAL_PORT,
8893                                 "Windows NT X86", /* FIXME */
8894                                 "localmon.dll");
8895         if (!W_ERROR_IS_OK(result)) {
8896                 goto out;
8897         }
8898
8899         result = fill_monitor_2(info, &info[1].info2,
8900                                 SPL_TCPIP_PORT,
8901                                 "Windows NT X86", /* FIXME */
8902                                 "tcpmon.dll");
8903         if (!W_ERROR_IS_OK(result)) {
8904                 goto out;
8905         }
8906
8907 out:
8908         if (!W_ERROR_IS_OK(result)) {
8909                 TALLOC_FREE(info);
8910                 *count = 0;
8911                 return result;
8912         }
8913
8914         *info_p = info;
8915
8916         return WERR_OK;
8917 }
8918
8919 /****************************************************************
8920  _spoolss_EnumMonitors
8921 ****************************************************************/
8922
8923 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
8924                              struct spoolss_EnumMonitors *r)
8925 {
8926         WERROR result;
8927
8928         /* that's an [in out] buffer */
8929
8930         if (!r->in.buffer && (r->in.offered != 0)) {
8931                 return WERR_INVALID_PARAM;
8932         }
8933
8934         DEBUG(5,("_spoolss_EnumMonitors\n"));
8935
8936         /*
8937          * Enumerate the print monitors ...
8938          *
8939          * Just reply with "Local Port", to keep NT happy
8940          * and I can use my nice printer checker.
8941          */
8942
8943         *r->out.count = 0;
8944         *r->out.needed = 0;
8945         *r->out.info = NULL;
8946
8947         switch (r->in.level) {
8948         case 1:
8949                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
8950                                                    r->out.count);
8951                 break;
8952         case 2:
8953                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
8954                                                    r->out.count);
8955                 break;
8956         default:
8957                 return WERR_UNKNOWN_LEVEL;
8958         }
8959
8960         if (!W_ERROR_IS_OK(result)) {
8961                 return result;
8962         }
8963
8964         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8965                                                      spoolss_EnumMonitors,
8966                                                      *r->out.info, r->in.level,
8967                                                      *r->out.count);
8968         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8969         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8970
8971         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8972 }
8973
8974 /****************************************************************************
8975 ****************************************************************************/
8976
8977 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
8978                              const print_queue_struct *queue,
8979                              int count, int snum,
8980                              struct spoolss_PrinterInfo2 *pinfo2,
8981                              uint32_t jobid,
8982                              struct spoolss_JobInfo1 *r)
8983 {
8984         int i = 0;
8985         bool found = false;
8986
8987         for (i=0; i<count; i++) {
8988                 if (queue[i].job == (int)jobid) {
8989                         found = true;
8990                         break;
8991                 }
8992         }
8993
8994         if (found == false) {
8995                 /* NT treats not found as bad param... yet another bad choice */
8996                 return WERR_INVALID_PARAM;
8997         }
8998
8999         return fill_job_info1(mem_ctx,
9000                               r,
9001                               &queue[i],
9002                               i,
9003                               snum,
9004                               pinfo2);
9005 }
9006
9007 /****************************************************************************
9008 ****************************************************************************/
9009
9010 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9011                              const print_queue_struct *queue,
9012                              int count, int snum,
9013                              struct spoolss_PrinterInfo2 *pinfo2,
9014                              uint32_t jobid,
9015                              struct spoolss_JobInfo2 *r)
9016 {
9017         int i = 0;
9018         bool found = false;
9019         struct spoolss_DeviceMode *devmode;
9020         WERROR result;
9021
9022         for (i=0; i<count; i++) {
9023                 if (queue[i].job == (int)jobid) {
9024                         found = true;
9025                         break;
9026                 }
9027         }
9028
9029         if (found == false) {
9030                 /* NT treats not found as bad param... yet another bad
9031                    choice */
9032                 return WERR_INVALID_PARAM;
9033         }
9034
9035         /*
9036          * if the print job does not have a DEVMODE associated with it,
9037          * just use the one for the printer. A NULL devicemode is not
9038          *  a failure condition
9039          */
9040
9041         devmode = print_job_devmode(lp_const_servicename(snum), jobid);
9042         if (!devmode) {
9043                 result = spoolss_create_default_devmode(mem_ctx,
9044                                                 pinfo2->printername,
9045                                                 &devmode);
9046                 if (!W_ERROR_IS_OK(result)) {
9047                         DEBUG(3, ("Can't proceed w/o a devmode!"));
9048                         return result;
9049                 }
9050         }
9051
9052         return fill_job_info2(mem_ctx,
9053                               r,
9054                               &queue[i],
9055                               i,
9056                               snum,
9057                               pinfo2,
9058                               devmode);
9059 }
9060
9061 /****************************************************************
9062  _spoolss_GetJob
9063 ****************************************************************/
9064
9065 WERROR _spoolss_GetJob(struct pipes_struct *p,
9066                        struct spoolss_GetJob *r)
9067 {
9068         WERROR result = WERR_OK;
9069         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9070         int snum;
9071         int count;
9072         print_queue_struct      *queue = NULL;
9073         print_status_struct prt_status;
9074
9075         /* that's an [in out] buffer */
9076
9077         if (!r->in.buffer && (r->in.offered != 0)) {
9078                 return WERR_INVALID_PARAM;
9079         }
9080
9081         DEBUG(5,("_spoolss_GetJob\n"));
9082
9083         *r->out.needed = 0;
9084
9085         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9086                 return WERR_BADFID;
9087         }
9088
9089         result = winreg_get_printer(p->mem_ctx,
9090                                     get_session_info_system(),
9091                                     p->msg_ctx,
9092                                     lp_const_servicename(snum),
9093                                     &pinfo2);
9094         if (!W_ERROR_IS_OK(result)) {
9095                 return result;
9096         }
9097
9098         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9099
9100         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9101                      count, prt_status.status, prt_status.message));
9102
9103         switch (r->in.level) {
9104         case 1:
9105                 result = getjob_level_1(p->mem_ctx,
9106                                         queue, count, snum, pinfo2,
9107                                         r->in.job_id, &r->out.info->info1);
9108                 break;
9109         case 2:
9110                 result = getjob_level_2(p->mem_ctx,
9111                                         queue, count, snum, pinfo2,
9112                                         r->in.job_id, &r->out.info->info2);
9113                 break;
9114         default:
9115                 result = WERR_UNKNOWN_LEVEL;
9116                 break;
9117         }
9118
9119         SAFE_FREE(queue);
9120         TALLOC_FREE(pinfo2);
9121
9122         if (!W_ERROR_IS_OK(result)) {
9123                 TALLOC_FREE(r->out.info);
9124                 return result;
9125         }
9126
9127         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9128                                                                                    r->in.level);
9129         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9130
9131         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9132 }
9133
9134 /****************************************************************
9135  _spoolss_GetPrinterDataEx
9136 ****************************************************************/
9137
9138 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9139                                  struct spoolss_GetPrinterDataEx *r)
9140 {
9141
9142         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9143         const char *printer;
9144         int                     snum = 0;
9145         WERROR result = WERR_OK;
9146         DATA_BLOB blob;
9147         enum winreg_Type val_type;
9148         uint8_t *val_data;
9149         uint32_t val_size;
9150
9151
9152         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9153
9154         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9155                 r->in.key_name, r->in.value_name));
9156
9157         /* in case of problem, return some default values */
9158
9159         *r->out.needed  = 0;
9160         *r->out.type    = REG_NONE;
9161
9162         if (!Printer) {
9163                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9164                         OUR_HANDLE(r->in.handle)));
9165                 result = WERR_BADFID;
9166                 goto done;
9167         }
9168
9169         /* Is the handle to a printer or to the server? */
9170
9171         if (Printer->printer_type == SPLHND_SERVER) {
9172
9173                 union spoolss_PrinterData data;
9174
9175                 result = getprinterdata_printer_server(p->mem_ctx,
9176                                                        r->in.value_name,
9177                                                        r->out.type,
9178                                                        &data);
9179                 if (!W_ERROR_IS_OK(result)) {
9180                         return result;
9181                 }
9182
9183                 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
9184                                                   *r->out.type, &data);
9185                 if (!W_ERROR_IS_OK(result)) {
9186                         return result;
9187                 }
9188
9189                 *r->out.needed = blob.length;
9190
9191                 if (r->in.offered >= *r->out.needed) {
9192                         memcpy(r->out.data, blob.data, blob.length);
9193                 }
9194
9195                 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9196         }
9197
9198         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9199                 return WERR_BADFID;
9200         }
9201         printer = lp_const_servicename(snum);
9202
9203         /* check to see if the keyname is valid */
9204         if (!strlen(r->in.key_name)) {
9205                 return WERR_INVALID_PARAM;
9206         }
9207
9208         /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9209         if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9210             strequal(r->in.value_name, "ChangeId")) {
9211                 *r->out.type = REG_DWORD;
9212                 *r->out.needed = 4;
9213                 if (r->in.offered >= *r->out.needed) {
9214                         uint32_t changeid = 0;
9215
9216                         result = winreg_printer_get_changeid(p->mem_ctx,
9217                                                              get_session_info_system(),
9218                                                              p->msg_ctx,
9219                                                              printer,
9220                                                              &changeid);
9221                         if (!W_ERROR_IS_OK(result)) {
9222                                 return result;
9223                         }
9224
9225                         SIVAL(r->out.data, 0, changeid);
9226                         result = WERR_OK;
9227                 }
9228                 goto done;
9229         }
9230
9231         result = winreg_get_printer_dataex(p->mem_ctx,
9232                                            get_session_info_system(),
9233                                            p->msg_ctx,
9234                                            printer,
9235                                            r->in.key_name,
9236                                            r->in.value_name,
9237                                            &val_type,
9238                                            &val_data,
9239                                            &val_size);
9240         if (!W_ERROR_IS_OK(result)) {
9241                 return result;
9242         }
9243
9244         *r->out.needed = val_size;
9245         *r->out.type = val_type;
9246
9247         if (r->in.offered >= *r->out.needed) {
9248                 memcpy(r->out.data, val_data, val_size);
9249         }
9250
9251  done:
9252         /* retain type when returning WERR_MORE_DATA */
9253         r->out.data     = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
9254
9255         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9256 }
9257
9258 /****************************************************************
9259  _spoolss_SetPrinterDataEx
9260 ****************************************************************/
9261
9262 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9263                                  struct spoolss_SetPrinterDataEx *r)
9264 {
9265         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9266         int                     snum = 0;
9267         WERROR                  result = WERR_OK;
9268         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9269         char                    *oid_string;
9270
9271         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9272
9273         /* From MSDN documentation of SetPrinterDataEx: pass request to
9274            SetPrinterData if key is "PrinterDriverData" */
9275
9276         if (!Printer) {
9277                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9278                         OUR_HANDLE(r->in.handle)));
9279                 return WERR_BADFID;
9280         }
9281
9282         if (Printer->printer_type == SPLHND_SERVER) {
9283                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9284                         "Not implemented for server handles yet\n"));
9285                 return WERR_INVALID_PARAM;
9286         }
9287
9288         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9289                 return WERR_BADFID;
9290         }
9291
9292         /*
9293          * Access check : NT returns "access denied" if you make a
9294          * SetPrinterData call without the necessary privildge.
9295          * we were originally returning OK if nothing changed
9296          * which made Win2k issue **a lot** of SetPrinterData
9297          * when connecting to a printer  --jerry
9298          */
9299
9300         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9301                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9302                         "change denied by handle access permissions\n"));
9303                 return WERR_ACCESS_DENIED;
9304         }
9305
9306         result = winreg_get_printer(Printer,
9307                                     get_session_info_system(),
9308                                     p->msg_ctx,
9309                                     lp_servicename(snum),
9310                                     &pinfo2);
9311         if (!W_ERROR_IS_OK(result)) {
9312                 return result;
9313         }
9314
9315         /* check for OID in valuename */
9316
9317         oid_string = strchr(r->in.value_name, ',');
9318         if (oid_string) {
9319                 *oid_string = '\0';
9320                 oid_string++;
9321         }
9322
9323         /* save the registry data */
9324
9325         result = winreg_set_printer_dataex(p->mem_ctx,
9326                                            get_session_info_system(),
9327                                            p->msg_ctx,
9328                                            pinfo2->sharename,
9329                                            r->in.key_name,
9330                                            r->in.value_name,
9331                                            r->in.type,
9332                                            r->in.data,
9333                                            r->in.offered);
9334
9335         if (W_ERROR_IS_OK(result)) {
9336                 /* save the OID if one was specified */
9337                 if (oid_string) {
9338                         char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9339                                 r->in.key_name, SPOOL_OID_KEY);
9340                         if (!str) {
9341                                 result = WERR_NOMEM;
9342                                 goto done;
9343                         }
9344
9345                         /*
9346                          * I'm not checking the status here on purpose.  Don't know
9347                          * if this is right, but I'm returning the status from the
9348                          * previous set_printer_dataex() call.  I have no idea if
9349                          * this is right.    --jerry
9350                          */
9351                         winreg_set_printer_dataex(p->mem_ctx,
9352                                                   get_session_info_system(),
9353                                                   p->msg_ctx,
9354                                                   pinfo2->sharename,
9355                                                   str,
9356                                                   r->in.value_name,
9357                                                   REG_SZ,
9358                                                   (uint8_t *) oid_string,
9359                                                   strlen(oid_string) + 1);
9360                 }
9361
9362                 result = winreg_printer_update_changeid(p->mem_ctx,
9363                                                         get_session_info_system(),
9364                                                         p->msg_ctx,
9365                                                         lp_const_servicename(snum));
9366
9367         }
9368
9369 done:
9370         talloc_free(pinfo2);
9371         return result;
9372 }
9373
9374 /****************************************************************
9375  _spoolss_DeletePrinterDataEx
9376 ****************************************************************/
9377
9378 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9379                                     struct spoolss_DeletePrinterDataEx *r)
9380 {
9381         const char *printer;
9382         int             snum=0;
9383         WERROR          status = WERR_OK;
9384         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9385
9386         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9387
9388         if (!Printer) {
9389                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9390                         "Invalid handle (%s:%u:%u).\n",
9391                         OUR_HANDLE(r->in.handle)));
9392                 return WERR_BADFID;
9393         }
9394
9395         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9396                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9397                         "printer properties change denied by handle\n"));
9398                 return WERR_ACCESS_DENIED;
9399         }
9400
9401         if (!r->in.value_name || !r->in.key_name) {
9402                 return WERR_NOMEM;
9403         }
9404
9405         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9406                 return WERR_BADFID;
9407         }
9408         printer = lp_const_servicename(snum);
9409
9410         status = winreg_delete_printer_dataex(p->mem_ctx,
9411                                               get_session_info_system(),
9412                                               p->msg_ctx,
9413                                               printer,
9414                                               r->in.key_name,
9415                                               r->in.value_name);
9416         if (W_ERROR_IS_OK(status)) {
9417                 status = winreg_printer_update_changeid(p->mem_ctx,
9418                                                         get_session_info_system(),
9419                                                         p->msg_ctx,
9420                                                         printer);
9421         }
9422
9423         return status;
9424 }
9425
9426 /****************************************************************
9427  _spoolss_EnumPrinterKey
9428 ****************************************************************/
9429
9430 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9431                                struct spoolss_EnumPrinterKey *r)
9432 {
9433         uint32_t        num_keys;
9434         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9435         int             snum = 0;
9436         WERROR          result = WERR_BADFILE;
9437         const char **array = NULL;
9438         DATA_BLOB blob;
9439
9440         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9441
9442         if (!Printer) {
9443                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9444                         OUR_HANDLE(r->in.handle)));
9445                 return WERR_BADFID;
9446         }
9447
9448         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9449                 return WERR_BADFID;
9450         }
9451
9452         result = winreg_enum_printer_key(p->mem_ctx,
9453                                          get_session_info_system(),
9454                                          p->msg_ctx,
9455                                          lp_const_servicename(snum),
9456                                          r->in.key_name,
9457                                          &num_keys,
9458                                          &array);
9459         if (!W_ERROR_IS_OK(result)) {
9460                 goto done;
9461         }
9462
9463         if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9464                 result = WERR_NOMEM;
9465                 goto done;
9466         }
9467
9468         *r->out._ndr_size = r->in.offered / 2;
9469         *r->out.needed = blob.length;
9470
9471         if (r->in.offered < *r->out.needed) {
9472                 result = WERR_MORE_DATA;
9473         } else {
9474                 result = WERR_OK;
9475                 r->out.key_buffer->string_array = array;
9476         }
9477
9478  done:
9479         if (!W_ERROR_IS_OK(result)) {
9480                 TALLOC_FREE(array);
9481                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9482                         *r->out.needed = 0;
9483                 }
9484         }
9485
9486         return result;
9487 }
9488
9489 /****************************************************************
9490  _spoolss_DeletePrinterKey
9491 ****************************************************************/
9492
9493 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9494                                  struct spoolss_DeletePrinterKey *r)
9495 {
9496         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9497         int                     snum=0;
9498         WERROR                  status;
9499         const char *printer;
9500
9501         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9502
9503         if (!Printer) {
9504                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9505                         OUR_HANDLE(r->in.handle)));
9506                 return WERR_BADFID;
9507         }
9508
9509         /* if keyname == NULL, return error */
9510         if ( !r->in.key_name )
9511                 return WERR_INVALID_PARAM;
9512
9513         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9514                 return WERR_BADFID;
9515         }
9516
9517         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9518                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9519                         "printer properties change denied by handle\n"));
9520                 return WERR_ACCESS_DENIED;
9521         }
9522
9523         printer = lp_const_servicename(snum);
9524
9525         /* delete the key and all subkeys */
9526         status = winreg_delete_printer_key(p->mem_ctx,
9527                                            get_session_info_system(),
9528                                            p->msg_ctx,
9529                                            printer,
9530                                            r->in.key_name);
9531         if (W_ERROR_IS_OK(status)) {
9532                 status = winreg_printer_update_changeid(p->mem_ctx,
9533                                                         get_session_info_system(),
9534                                                         p->msg_ctx,
9535                                                         printer);
9536         }
9537
9538         return status;
9539 }
9540
9541 /****************************************************************
9542  _spoolss_EnumPrinterDataEx
9543 ****************************************************************/
9544
9545 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
9546                                   struct spoolss_EnumPrinterDataEx *r)
9547 {
9548         uint32_t        count = 0;
9549         struct spoolss_PrinterEnumValues *info = NULL;
9550         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9551         int             snum;
9552         WERROR          result;
9553
9554         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9555
9556         *r->out.count = 0;
9557         *r->out.needed = 0;
9558         *r->out.info = NULL;
9559
9560         if (!Printer) {
9561                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9562                         OUR_HANDLE(r->in.handle)));
9563                 return WERR_BADFID;
9564         }
9565
9566         /*
9567          * first check for a keyname of NULL or "".  Win2k seems to send
9568          * this a lot and we should send back WERR_INVALID_PARAM
9569          * no need to spend time looking up the printer in this case.
9570          * --jerry
9571          */
9572
9573         if (!strlen(r->in.key_name)) {
9574                 result = WERR_INVALID_PARAM;
9575                 goto done;
9576         }
9577
9578         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9579                 return WERR_BADFID;
9580         }
9581
9582         /* now look for a match on the key name */
9583         result = winreg_enum_printer_dataex(p->mem_ctx,
9584                                             get_session_info_system(),
9585                                             p->msg_ctx,
9586                                             lp_const_servicename(snum),
9587                                             r->in.key_name,
9588                                             &count,
9589                                             &info);
9590         if (!W_ERROR_IS_OK(result)) {
9591                 goto done;
9592         }
9593
9594 #if 0 /* FIXME - gd */
9595         /* housekeeping information in the reply */
9596
9597         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9598          * the hand marshalled container size is a multiple
9599          * of 4 bytes for RPC alignment.
9600          */
9601
9602         if (needed % 4) {
9603                 needed += 4-(needed % 4);
9604         }
9605 #endif
9606         *r->out.count   = count;
9607         *r->out.info    = info;
9608
9609  done:
9610         if (!W_ERROR_IS_OK(result)) {
9611                 return result;
9612         }
9613
9614         *r->out.needed  = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9615                                                spoolss_EnumPrinterDataEx,
9616                                                *r->out.info,
9617                                                *r->out.count);
9618         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9619         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9620
9621         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9622 }
9623
9624 /****************************************************************************
9625 ****************************************************************************/
9626
9627 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9628                                                  const char *servername,
9629                                                  const char *environment,
9630                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
9631 {
9632         WERROR werr;
9633         char *path = NULL;
9634
9635         werr = compose_spoolss_server_path(mem_ctx,
9636                                            servername,
9637                                            environment,
9638                                            SPOOLSS_PRTPROCS_PATH,
9639                                            &path);
9640         if (!W_ERROR_IS_OK(werr)) {
9641                 return werr;
9642         }
9643
9644         DEBUG(4,("print processor directory: [%s]\n", path));
9645
9646         r->directory_name = path;
9647
9648         return WERR_OK;
9649 }
9650
9651 /****************************************************************
9652  _spoolss_GetPrintProcessorDirectory
9653 ****************************************************************/
9654
9655 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
9656                                            struct spoolss_GetPrintProcessorDirectory *r)
9657 {
9658         WERROR result;
9659         char *prnproc_share = NULL;
9660         bool prnproc_share_exists = false;
9661         int snum;
9662
9663         /* that's an [in out] buffer */
9664
9665         if (!r->in.buffer && (r->in.offered != 0)) {
9666                 return WERR_INVALID_PARAM;
9667         }
9668
9669         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9670                 r->in.level));
9671
9672         *r->out.needed = 0;
9673
9674         /* r->in.level is ignored */
9675
9676         /* We always should reply with a local print processor directory so that
9677          * users are not forced to have a [prnproc$] share on the Samba spoolss
9678          * server, if users decide to do so, lets announce it though - Guenther */
9679
9680         snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
9681         if (!prnproc_share) {
9682                 return WERR_NOMEM;
9683         }
9684         if (snum != -1) {
9685                 prnproc_share_exists = true;
9686         }
9687
9688         result = getprintprocessordirectory_level_1(p->mem_ctx,
9689                                                     prnproc_share_exists ? r->in.server : NULL,
9690                                                     r->in.environment,
9691                                                     &r->out.info->info1);
9692         if (!W_ERROR_IS_OK(result)) {
9693                 TALLOC_FREE(r->out.info);
9694                 return result;
9695         }
9696
9697         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
9698                                                                                    r->out.info, r->in.level);
9699         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9700
9701         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9702 }
9703
9704 /*******************************************************************
9705  ********************************************************************/
9706
9707 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9708                                const char *dllname)
9709 {
9710         enum ndr_err_code ndr_err;
9711         struct spoolss_MonitorUi ui;
9712
9713         ui.dll_name = dllname;
9714
9715         ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
9716                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9717         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9718                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9719         }
9720         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9721 }
9722
9723 /*******************************************************************
9724  Streams the monitor UI DLL name in UNICODE
9725 *******************************************************************/
9726
9727 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9728                                struct security_token *token, DATA_BLOB *in,
9729                                DATA_BLOB *out, uint32_t *needed)
9730 {
9731         const char *dllname = "tcpmonui.dll";
9732
9733         *needed = (strlen(dllname)+1) * 2;
9734
9735         if (out->length < *needed) {
9736                 return WERR_INSUFFICIENT_BUFFER;
9737         }
9738
9739         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9740                 return WERR_NOMEM;
9741         }
9742
9743         return WERR_OK;
9744 }
9745
9746 /*******************************************************************
9747  ********************************************************************/
9748
9749 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9750                              struct spoolss_PortData1 *port1,
9751                              const DATA_BLOB *buf)
9752 {
9753         enum ndr_err_code ndr_err;
9754         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
9755                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9756         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9757                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9758         }
9759         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9760 }
9761
9762 /*******************************************************************
9763  ********************************************************************/
9764
9765 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9766                              struct spoolss_PortData2 *port2,
9767                              const DATA_BLOB *buf)
9768 {
9769         enum ndr_err_code ndr_err;
9770         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
9771                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9772         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9773                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9774         }
9775         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9776 }
9777
9778 /*******************************************************************
9779  Create a new TCP/IP port
9780 *******************************************************************/
9781
9782 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9783                              struct security_token *token, DATA_BLOB *in,
9784                              DATA_BLOB *out, uint32_t *needed)
9785 {
9786         struct spoolss_PortData1 port1;
9787         struct spoolss_PortData2 port2;
9788         char *device_uri = NULL;
9789         uint32_t version;
9790
9791         const char *portname;
9792         const char *hostaddress;
9793         const char *queue;
9794         uint32_t port_number;
9795         uint32_t protocol;
9796
9797         /* peek for spoolss_PortData version */
9798
9799         if (!in || (in->length < (128 + 4))) {
9800                 return WERR_GENERAL_FAILURE;
9801         }
9802
9803         version = IVAL(in->data, 128);
9804
9805         switch (version) {
9806                 case 1:
9807                         ZERO_STRUCT(port1);
9808
9809                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
9810                                 return WERR_NOMEM;
9811                         }
9812
9813                         portname        = port1.portname;
9814                         hostaddress     = port1.hostaddress;
9815                         queue           = port1.queue;
9816                         protocol        = port1.protocol;
9817                         port_number     = port1.port_number;
9818
9819                         break;
9820                 case 2:
9821                         ZERO_STRUCT(port2);
9822
9823                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
9824                                 return WERR_NOMEM;
9825                         }
9826
9827                         portname        = port2.portname;
9828                         hostaddress     = port2.hostaddress;
9829                         queue           = port2.queue;
9830                         protocol        = port2.protocol;
9831                         port_number     = port2.port_number;
9832
9833                         break;
9834                 default:
9835                         DEBUG(1,("xcvtcp_addport: "
9836                                 "unknown version of port_data: %d\n", version));
9837                         return WERR_UNKNOWN_PORT;
9838         }
9839
9840         /* create the device URI and call the add_port_hook() */
9841
9842         switch (protocol) {
9843         case PROTOCOL_RAWTCP_TYPE:
9844                 device_uri = talloc_asprintf(mem_ctx,
9845                                 "socket://%s:%d/", hostaddress,
9846                                 port_number);
9847                 break;
9848
9849         case PROTOCOL_LPR_TYPE:
9850                 device_uri = talloc_asprintf(mem_ctx,
9851                         "lpr://%s/%s", hostaddress, queue );
9852                 break;
9853
9854         default:
9855                 return WERR_UNKNOWN_PORT;
9856         }
9857
9858         if (!device_uri) {
9859                 return WERR_NOMEM;
9860         }
9861
9862         return add_port_hook(mem_ctx, token, portname, device_uri);
9863 }
9864
9865 /*******************************************************************
9866 *******************************************************************/
9867
9868 struct xcv_api_table xcvtcp_cmds[] = {
9869         { "MonitorUI",  xcvtcp_monitorui },
9870         { "AddPort",    xcvtcp_addport},
9871         { NULL,         NULL }
9872 };
9873
9874 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
9875                                      struct security_token *token, const char *command,
9876                                      DATA_BLOB *inbuf,
9877                                      DATA_BLOB *outbuf,
9878                                      uint32_t *needed )
9879 {
9880         int i;
9881
9882         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9883
9884         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9885                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9886                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9887         }
9888
9889         return WERR_BADFUNC;
9890 }
9891
9892 /*******************************************************************
9893 *******************************************************************/
9894 #if 0   /* don't support management using the "Local Port" monitor */
9895
9896 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
9897                                  struct security_token *token, DATA_BLOB *in,
9898                                  DATA_BLOB *out, uint32_t *needed)
9899 {
9900         const char *dllname = "localui.dll";
9901
9902         *needed = (strlen(dllname)+1) * 2;
9903
9904         if (out->length < *needed) {
9905                 return WERR_INSUFFICIENT_BUFFER;
9906         }
9907
9908         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9909                 return WERR_NOMEM;
9910         }
9911
9912         return WERR_OK;
9913 }
9914
9915 /*******************************************************************
9916 *******************************************************************/
9917
9918 struct xcv_api_table xcvlocal_cmds[] = {
9919         { "MonitorUI",  xcvlocal_monitorui },
9920         { NULL,         NULL }
9921 };
9922 #else
9923 struct xcv_api_table xcvlocal_cmds[] = {
9924         { NULL,         NULL }
9925 };
9926 #endif
9927
9928
9929
9930 /*******************************************************************
9931 *******************************************************************/
9932
9933 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
9934                                        struct security_token *token, const char *command,
9935                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
9936                                        uint32_t *needed)
9937 {
9938         int i;
9939
9940         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9941
9942         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9943                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9944                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
9945         }
9946         return WERR_BADFUNC;
9947 }
9948
9949 /****************************************************************
9950  _spoolss_XcvData
9951 ****************************************************************/
9952
9953 WERROR _spoolss_XcvData(struct pipes_struct *p,
9954                         struct spoolss_XcvData *r)
9955 {
9956         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9957         DATA_BLOB out_data = data_blob_null;
9958         WERROR werror;
9959
9960         if (!Printer) {
9961                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9962                         OUR_HANDLE(r->in.handle)));
9963                 return WERR_BADFID;
9964         }
9965
9966         /* Has to be a handle to the TCP/IP port monitor */
9967
9968         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9969                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9970                 return WERR_BADFID;
9971         }
9972
9973         /* requires administrative access to the server */
9974
9975         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9976                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9977                 return WERR_ACCESS_DENIED;
9978         }
9979
9980         /* Allocate the outgoing buffer */
9981
9982         if (r->in.out_data_size) {
9983                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
9984                 if (out_data.data == NULL) {
9985                         return WERR_NOMEM;
9986                 }
9987         }
9988
9989         switch ( Printer->printer_type ) {
9990         case SPLHND_PORTMON_TCP:
9991                 werror = process_xcvtcp_command(p->mem_ctx,
9992                                                 p->session_info->security_token,
9993                                                 r->in.function_name,
9994                                                 &r->in.in_data, &out_data,
9995                                                 r->out.needed);
9996                 break;
9997         case SPLHND_PORTMON_LOCAL:
9998                 werror = process_xcvlocal_command(p->mem_ctx,
9999                                                   p->session_info->security_token,
10000                                                   r->in.function_name,
10001                                                   &r->in.in_data, &out_data,
10002                                                   r->out.needed);
10003                 break;
10004         default:
10005                 werror = WERR_INVALID_PRINT_MONITOR;
10006         }
10007
10008         if (!W_ERROR_IS_OK(werror)) {
10009                 return werror;
10010         }
10011
10012         *r->out.status_code = 0;
10013
10014         if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10015                 memcpy(r->out.out_data, out_data.data,
10016                         MIN(r->in.out_data_size, out_data.length));
10017         }
10018
10019         return WERR_OK;
10020 }
10021
10022 /****************************************************************
10023  _spoolss_AddPrintProcessor
10024 ****************************************************************/
10025
10026 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10027                                   struct spoolss_AddPrintProcessor *r)
10028 {
10029         /* for now, just indicate success and ignore the add.  We'll
10030            automatically set the winprint processor for printer
10031            entries later.  Used to debug the LexMark Optra S 1855 PCL
10032            driver --jerry */
10033
10034         return WERR_OK;
10035 }
10036
10037 /****************************************************************
10038  _spoolss_AddPort
10039 ****************************************************************/
10040
10041 WERROR _spoolss_AddPort(struct pipes_struct *p,
10042                         struct spoolss_AddPort *r)
10043 {
10044         /* do what w2k3 does */
10045
10046         return WERR_NOT_SUPPORTED;
10047 }
10048
10049 /****************************************************************
10050  _spoolss_GetPrinterDriver
10051 ****************************************************************/
10052
10053 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10054                                  struct spoolss_GetPrinterDriver *r)
10055 {
10056         p->rng_fault_state = true;
10057         return WERR_NOT_SUPPORTED;
10058 }
10059
10060 /****************************************************************
10061  _spoolss_ReadPrinter
10062 ****************************************************************/
10063
10064 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10065                             struct spoolss_ReadPrinter *r)
10066 {
10067         p->rng_fault_state = true;
10068         return WERR_NOT_SUPPORTED;
10069 }
10070
10071 /****************************************************************
10072  _spoolss_WaitForPrinterChange
10073 ****************************************************************/
10074
10075 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10076                                      struct spoolss_WaitForPrinterChange *r)
10077 {
10078         p->rng_fault_state = true;
10079         return WERR_NOT_SUPPORTED;
10080 }
10081
10082 /****************************************************************
10083  _spoolss_ConfigurePort
10084 ****************************************************************/
10085
10086 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10087                               struct spoolss_ConfigurePort *r)
10088 {
10089         p->rng_fault_state = true;
10090         return WERR_NOT_SUPPORTED;
10091 }
10092
10093 /****************************************************************
10094  _spoolss_DeletePort
10095 ****************************************************************/
10096
10097 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10098                            struct spoolss_DeletePort *r)
10099 {
10100         p->rng_fault_state = true;
10101         return WERR_NOT_SUPPORTED;
10102 }
10103
10104 /****************************************************************
10105  _spoolss_CreatePrinterIC
10106 ****************************************************************/
10107
10108 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10109                                 struct spoolss_CreatePrinterIC *r)
10110 {
10111         p->rng_fault_state = true;
10112         return WERR_NOT_SUPPORTED;
10113 }
10114
10115 /****************************************************************
10116  _spoolss_PlayGDIScriptOnPrinterIC
10117 ****************************************************************/
10118
10119 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10120                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
10121 {
10122         p->rng_fault_state = true;
10123         return WERR_NOT_SUPPORTED;
10124 }
10125
10126 /****************************************************************
10127  _spoolss_DeletePrinterIC
10128 ****************************************************************/
10129
10130 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10131                                 struct spoolss_DeletePrinterIC *r)
10132 {
10133         p->rng_fault_state = true;
10134         return WERR_NOT_SUPPORTED;
10135 }
10136
10137 /****************************************************************
10138  _spoolss_AddPrinterConnection
10139 ****************************************************************/
10140
10141 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10142                                      struct spoolss_AddPrinterConnection *r)
10143 {
10144         p->rng_fault_state = true;
10145         return WERR_NOT_SUPPORTED;
10146 }
10147
10148 /****************************************************************
10149  _spoolss_DeletePrinterConnection
10150 ****************************************************************/
10151
10152 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10153                                         struct spoolss_DeletePrinterConnection *r)
10154 {
10155         p->rng_fault_state = true;
10156         return WERR_NOT_SUPPORTED;
10157 }
10158
10159 /****************************************************************
10160  _spoolss_PrinterMessageBox
10161 ****************************************************************/
10162
10163 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10164                                   struct spoolss_PrinterMessageBox *r)
10165 {
10166         p->rng_fault_state = true;
10167         return WERR_NOT_SUPPORTED;
10168 }
10169
10170 /****************************************************************
10171  _spoolss_AddMonitor
10172 ****************************************************************/
10173
10174 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10175                            struct spoolss_AddMonitor *r)
10176 {
10177         p->rng_fault_state = true;
10178         return WERR_NOT_SUPPORTED;
10179 }
10180
10181 /****************************************************************
10182  _spoolss_DeleteMonitor
10183 ****************************************************************/
10184
10185 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10186                               struct spoolss_DeleteMonitor *r)
10187 {
10188         p->rng_fault_state = true;
10189         return WERR_NOT_SUPPORTED;
10190 }
10191
10192 /****************************************************************
10193  _spoolss_DeletePrintProcessor
10194 ****************************************************************/
10195
10196 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10197                                      struct spoolss_DeletePrintProcessor *r)
10198 {
10199         p->rng_fault_state = true;
10200         return WERR_NOT_SUPPORTED;
10201 }
10202
10203 /****************************************************************
10204  _spoolss_AddPrintProvidor
10205 ****************************************************************/
10206
10207 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10208                                  struct spoolss_AddPrintProvidor *r)
10209 {
10210         p->rng_fault_state = true;
10211         return WERR_NOT_SUPPORTED;
10212 }
10213
10214 /****************************************************************
10215  _spoolss_DeletePrintProvidor
10216 ****************************************************************/
10217
10218 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10219                                     struct spoolss_DeletePrintProvidor *r)
10220 {
10221         p->rng_fault_state = true;
10222         return WERR_NOT_SUPPORTED;
10223 }
10224
10225 /****************************************************************
10226  _spoolss_FindFirstPrinterChangeNotification
10227 ****************************************************************/
10228
10229 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10230                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
10231 {
10232         p->rng_fault_state = true;
10233         return WERR_NOT_SUPPORTED;
10234 }
10235
10236 /****************************************************************
10237  _spoolss_FindNextPrinterChangeNotification
10238 ****************************************************************/
10239
10240 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10241                                                   struct spoolss_FindNextPrinterChangeNotification *r)
10242 {
10243         p->rng_fault_state = true;
10244         return WERR_NOT_SUPPORTED;
10245 }
10246
10247 /****************************************************************
10248  _spoolss_RouterFindFirstPrinterChangeNotificationOld
10249 ****************************************************************/
10250
10251 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10252                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10253 {
10254         p->rng_fault_state = true;
10255         return WERR_NOT_SUPPORTED;
10256 }
10257
10258 /****************************************************************
10259  _spoolss_ReplyOpenPrinter
10260 ****************************************************************/
10261
10262 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10263                                  struct spoolss_ReplyOpenPrinter *r)
10264 {
10265         p->rng_fault_state = true;
10266         return WERR_NOT_SUPPORTED;
10267 }
10268
10269 /****************************************************************
10270  _spoolss_RouterReplyPrinter
10271 ****************************************************************/
10272
10273 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10274                                    struct spoolss_RouterReplyPrinter *r)
10275 {
10276         p->rng_fault_state = true;
10277         return WERR_NOT_SUPPORTED;
10278 }
10279
10280 /****************************************************************
10281  _spoolss_ReplyClosePrinter
10282 ****************************************************************/
10283
10284 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10285                                   struct spoolss_ReplyClosePrinter *r)
10286 {
10287         p->rng_fault_state = true;
10288         return WERR_NOT_SUPPORTED;
10289 }
10290
10291 /****************************************************************
10292  _spoolss_AddPortEx
10293 ****************************************************************/
10294
10295 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10296                           struct spoolss_AddPortEx *r)
10297 {
10298         p->rng_fault_state = true;
10299         return WERR_NOT_SUPPORTED;
10300 }
10301
10302 /****************************************************************
10303  _spoolss_RouterFindFirstPrinterChangeNotification
10304 ****************************************************************/
10305
10306 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10307                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10308 {
10309         p->rng_fault_state = true;
10310         return WERR_NOT_SUPPORTED;
10311 }
10312
10313 /****************************************************************
10314  _spoolss_SpoolerInit
10315 ****************************************************************/
10316
10317 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10318                             struct spoolss_SpoolerInit *r)
10319 {
10320         p->rng_fault_state = true;
10321         return WERR_NOT_SUPPORTED;
10322 }
10323
10324 /****************************************************************
10325  _spoolss_ResetPrinterEx
10326 ****************************************************************/
10327
10328 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10329                                struct spoolss_ResetPrinterEx *r)
10330 {
10331         p->rng_fault_state = true;
10332         return WERR_NOT_SUPPORTED;
10333 }
10334
10335 /****************************************************************
10336  _spoolss_RouterReplyPrinterEx
10337 ****************************************************************/
10338
10339 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10340                                      struct spoolss_RouterReplyPrinterEx *r)
10341 {
10342         p->rng_fault_state = true;
10343         return WERR_NOT_SUPPORTED;
10344 }
10345
10346 /****************************************************************
10347  _spoolss_44
10348 ****************************************************************/
10349
10350 WERROR _spoolss_44(struct pipes_struct *p,
10351                    struct spoolss_44 *r)
10352 {
10353         p->rng_fault_state = true;
10354         return WERR_NOT_SUPPORTED;
10355 }
10356
10357 /****************************************************************
10358  _spoolss_SetPort
10359 ****************************************************************/
10360
10361 WERROR _spoolss_SetPort(struct pipes_struct *p,
10362                         struct spoolss_SetPort *r)
10363 {
10364         p->rng_fault_state = true;
10365         return WERR_NOT_SUPPORTED;
10366 }
10367
10368 /****************************************************************
10369  _spoolss_4a
10370 ****************************************************************/
10371
10372 WERROR _spoolss_4a(struct pipes_struct *p,
10373                    struct spoolss_4a *r)
10374 {
10375         p->rng_fault_state = true;
10376         return WERR_NOT_SUPPORTED;
10377 }
10378
10379 /****************************************************************
10380  _spoolss_4b
10381 ****************************************************************/
10382
10383 WERROR _spoolss_4b(struct pipes_struct *p,
10384                    struct spoolss_4b *r)
10385 {
10386         p->rng_fault_state = true;
10387         return WERR_NOT_SUPPORTED;
10388 }
10389
10390 /****************************************************************
10391  _spoolss_4c
10392 ****************************************************************/
10393
10394 WERROR _spoolss_4c(struct pipes_struct *p,
10395                    struct spoolss_4c *r)
10396 {
10397         p->rng_fault_state = true;
10398         return WERR_NOT_SUPPORTED;
10399 }
10400
10401 /****************************************************************
10402  _spoolss_53
10403 ****************************************************************/
10404
10405 WERROR _spoolss_53(struct pipes_struct *p,
10406                    struct spoolss_53 *r)
10407 {
10408         p->rng_fault_state = true;
10409         return WERR_NOT_SUPPORTED;
10410 }
10411
10412 /****************************************************************
10413  _spoolss_AddPerMachineConnection
10414 ****************************************************************/
10415
10416 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
10417                                         struct spoolss_AddPerMachineConnection *r)
10418 {
10419         p->rng_fault_state = true;
10420         return WERR_NOT_SUPPORTED;
10421 }
10422
10423 /****************************************************************
10424  _spoolss_DeletePerMachineConnection
10425 ****************************************************************/
10426
10427 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
10428                                            struct spoolss_DeletePerMachineConnection *r)
10429 {
10430         p->rng_fault_state = true;
10431         return WERR_NOT_SUPPORTED;
10432 }
10433
10434 /****************************************************************
10435  _spoolss_EnumPerMachineConnections
10436 ****************************************************************/
10437
10438 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
10439                                           struct spoolss_EnumPerMachineConnections *r)
10440 {
10441         p->rng_fault_state = true;
10442         return WERR_NOT_SUPPORTED;
10443 }
10444
10445 /****************************************************************
10446  _spoolss_5a
10447 ****************************************************************/
10448
10449 WERROR _spoolss_5a(struct pipes_struct *p,
10450                    struct spoolss_5a *r)
10451 {
10452         p->rng_fault_state = true;
10453         return WERR_NOT_SUPPORTED;
10454 }
10455
10456 /****************************************************************
10457  _spoolss_5b
10458 ****************************************************************/
10459
10460 WERROR _spoolss_5b(struct pipes_struct *p,
10461                    struct spoolss_5b *r)
10462 {
10463         p->rng_fault_state = true;
10464         return WERR_NOT_SUPPORTED;
10465 }
10466
10467 /****************************************************************
10468  _spoolss_5c
10469 ****************************************************************/
10470
10471 WERROR _spoolss_5c(struct pipes_struct *p,
10472                    struct spoolss_5c *r)
10473 {
10474         p->rng_fault_state = true;
10475         return WERR_NOT_SUPPORTED;
10476 }
10477
10478 /****************************************************************
10479  _spoolss_5d
10480 ****************************************************************/
10481
10482 WERROR _spoolss_5d(struct pipes_struct *p,
10483                    struct spoolss_5d *r)
10484 {
10485         p->rng_fault_state = true;
10486         return WERR_NOT_SUPPORTED;
10487 }
10488
10489 /****************************************************************
10490  _spoolss_5e
10491 ****************************************************************/
10492
10493 WERROR _spoolss_5e(struct pipes_struct *p,
10494                    struct spoolss_5e *r)
10495 {
10496         p->rng_fault_state = true;
10497         return WERR_NOT_SUPPORTED;
10498 }
10499
10500 /****************************************************************
10501  _spoolss_5f
10502 ****************************************************************/
10503
10504 WERROR _spoolss_5f(struct pipes_struct *p,
10505                    struct spoolss_5f *r)
10506 {
10507         p->rng_fault_state = true;
10508         return WERR_NOT_SUPPORTED;
10509 }
10510
10511 /****************************************************************
10512  _spoolss_60
10513 ****************************************************************/
10514
10515 WERROR _spoolss_60(struct pipes_struct *p,
10516                    struct spoolss_60 *r)
10517 {
10518         p->rng_fault_state = true;
10519         return WERR_NOT_SUPPORTED;
10520 }
10521
10522 /****************************************************************
10523  _spoolss_61
10524 ****************************************************************/
10525
10526 WERROR _spoolss_61(struct pipes_struct *p,
10527                    struct spoolss_61 *r)
10528 {
10529         p->rng_fault_state = true;
10530         return WERR_NOT_SUPPORTED;
10531 }
10532
10533 /****************************************************************
10534  _spoolss_62
10535 ****************************************************************/
10536
10537 WERROR _spoolss_62(struct pipes_struct *p,
10538                    struct spoolss_62 *r)
10539 {
10540         p->rng_fault_state = true;
10541         return WERR_NOT_SUPPORTED;
10542 }
10543
10544 /****************************************************************
10545  _spoolss_63
10546 ****************************************************************/
10547
10548 WERROR _spoolss_63(struct pipes_struct *p,
10549                    struct spoolss_63 *r)
10550 {
10551         p->rng_fault_state = true;
10552         return WERR_NOT_SUPPORTED;
10553 }
10554
10555 /****************************************************************
10556  _spoolss_64
10557 ****************************************************************/
10558
10559 WERROR _spoolss_64(struct pipes_struct *p,
10560                    struct spoolss_64 *r)
10561 {
10562         p->rng_fault_state = true;
10563         return WERR_NOT_SUPPORTED;
10564 }
10565
10566 /****************************************************************
10567  _spoolss_65
10568 ****************************************************************/
10569
10570 WERROR _spoolss_65(struct pipes_struct *p,
10571                    struct spoolss_65 *r)
10572 {
10573         p->rng_fault_state = true;
10574         return WERR_NOT_SUPPORTED;
10575 }
10576
10577 /****************************************************************
10578  _spoolss_GetCorePrinterDrivers
10579 ****************************************************************/
10580
10581 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
10582                                       struct spoolss_GetCorePrinterDrivers *r)
10583 {
10584         p->rng_fault_state = true;
10585         return WERR_NOT_SUPPORTED;
10586 }
10587
10588 /****************************************************************
10589  _spoolss_67
10590 ****************************************************************/
10591
10592 WERROR _spoolss_67(struct pipes_struct *p,
10593                    struct spoolss_67 *r)
10594 {
10595         p->rng_fault_state = true;
10596         return WERR_NOT_SUPPORTED;
10597 }
10598
10599 /****************************************************************
10600  _spoolss_GetPrinterDriverPackagePath
10601 ****************************************************************/
10602
10603 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
10604                                             struct spoolss_GetPrinterDriverPackagePath *r)
10605 {
10606         p->rng_fault_state = true;
10607         return WERR_NOT_SUPPORTED;
10608 }
10609
10610 /****************************************************************
10611  _spoolss_69
10612 ****************************************************************/
10613
10614 WERROR _spoolss_69(struct pipes_struct *p,
10615                    struct spoolss_69 *r)
10616 {
10617         p->rng_fault_state = true;
10618         return WERR_NOT_SUPPORTED;
10619 }
10620
10621 /****************************************************************
10622  _spoolss_6a
10623 ****************************************************************/
10624
10625 WERROR _spoolss_6a(struct pipes_struct *p,
10626                    struct spoolss_6a *r)
10627 {
10628         p->rng_fault_state = true;
10629         return WERR_NOT_SUPPORTED;
10630 }
10631
10632 /****************************************************************
10633  _spoolss_6b
10634 ****************************************************************/
10635
10636 WERROR _spoolss_6b(struct pipes_struct *p,
10637                    struct spoolss_6b *r)
10638 {
10639         p->rng_fault_state = true;
10640         return WERR_NOT_SUPPORTED;
10641 }
10642
10643 /****************************************************************
10644  _spoolss_6c
10645 ****************************************************************/
10646
10647 WERROR _spoolss_6c(struct pipes_struct *p,
10648                    struct spoolss_6c *r)
10649 {
10650         p->rng_fault_state = true;
10651         return WERR_NOT_SUPPORTED;
10652 }
10653
10654 /****************************************************************
10655  _spoolss_6d
10656 ****************************************************************/
10657
10658 WERROR _spoolss_6d(struct pipes_struct *p,
10659                    struct spoolss_6d *r)
10660 {
10661         p->rng_fault_state = true;
10662         return WERR_NOT_SUPPORTED;
10663 }