s3-printing: safe a ton of roundtrips by reusing existing winreg binding_handles.
[sfrench/samba-autobuild/.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 "ntdomain.h"
32 #include "nt_printing.h"
33 #include "srv_spoolss_util.h"
34 #include "../librpc/gen_ndr/srv_spoolss.h"
35 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
36 #include "rpc_client/init_spoolss.h"
37 #include "rpc_client/cli_pipe.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 #include "../libcli/registry/util_reg.h"
49 #include "smbd/smbd.h"
50 #include "smbd/globals.h"
51 #include "auth.h"
52 #include "messages.h"
53 #include "rpc_server/spoolss/srv_spoolss_nt.h"
54 #include "util_tdb.h"
55 #include "libsmb/libsmb.h"
56 #include "printing/printer_list.h"
57 #include "../lib/tsocket/tsocket.h"
58 #include "rpc_client/cli_winreg_spoolss.h"
59
60 /* macros stolen from s4 spoolss server */
61 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
62         ((info)?ndr_size_##fn(info, level, 0):0)
63
64 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
65         ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
66
67 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
68         ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
69
70 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
71
72 #undef DBGC_CLASS
73 #define DBGC_CLASS DBGC_RPC_SRV
74
75 #ifndef MAX_OPEN_PRINTER_EXS
76 #define MAX_OPEN_PRINTER_EXS 50
77 #endif
78
79 struct notify_back_channel;
80
81 /* structure to store the printer handles */
82 /* and a reference to what it's pointing to */
83 /* and the notify info asked about */
84 /* that's the central struct */
85 struct printer_handle {
86         struct printer_handle *prev, *next;
87         bool document_started;
88         bool page_started;
89         uint32 jobid; /* jobid in printing backend */
90         int printer_type;
91         const char *servername;
92         fstring sharename;
93         uint32 type;
94         uint32 access_granted;
95         struct {
96                 uint32 flags;
97                 uint32 options;
98                 fstring localmachine;
99                 uint32 printerlocal;
100                 struct spoolss_NotifyOption *option;
101                 struct policy_handle cli_hnd;
102                 struct notify_back_channel *cli_chan;
103                 uint32 change;
104                 /* are we in a FindNextPrinterChangeNotify() call? */
105                 bool fnpcn;
106                 struct messaging_context *msg_ctx;
107         } notify;
108         struct {
109                 fstring machine;
110                 fstring user;
111         } client;
112
113         /* devmode sent in the OpenPrinter() call */
114         struct spoolss_DeviceMode *devmode;
115
116         /* TODO cache the printer info2 structure */
117         struct spoolss_PrinterInfo2 *info2;
118
119 };
120
121 static struct printer_handle *printers_list;
122
123 struct printer_session_counter {
124         struct printer_session_counter *next;
125         struct printer_session_counter *prev;
126
127         int snum;
128         uint32_t counter;
129 };
130
131 static struct printer_session_counter *counter_list;
132
133 struct notify_back_channel {
134         struct notify_back_channel *prev, *next;
135
136         /* associated client */
137         struct sockaddr_storage client_address;
138
139         /* print notify back-channel pipe handle*/
140         struct rpc_pipe_client *cli_pipe;
141         struct dcerpc_binding_handle *binding_handle;
142         uint32_t active_connections;
143 };
144
145 static struct notify_back_channel *back_channels;
146
147 /* Map generic permissions to printer object specific permissions */
148
149 const struct standard_mapping printer_std_mapping = {
150         PRINTER_READ,
151         PRINTER_WRITE,
152         PRINTER_EXECUTE,
153         PRINTER_ALL_ACCESS
154 };
155
156 /* Map generic permissions to print server object specific permissions */
157
158 const struct standard_mapping printserver_std_mapping = {
159         SERVER_READ,
160         SERVER_WRITE,
161         SERVER_EXECUTE,
162         SERVER_ALL_ACCESS
163 };
164
165 /* API table for Xcv Monitor functions */
166
167 struct xcv_api_table {
168         const char *name;
169         WERROR(*fn) (TALLOC_CTX *mem_ctx, struct security_token *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
170 };
171
172 static void prune_printername_cache(void);
173
174 /********************************************************************
175  * Canonicalize servername.
176  ********************************************************************/
177
178 static const char *canon_servername(const char *servername)
179 {
180         const char *pservername = servername;
181         while (*pservername == '\\') {
182                 pservername++;
183         }
184         return pservername;
185 }
186
187 /* translate between internal status numbers and NT status numbers */
188 static int nt_printj_status(int v)
189 {
190         switch (v) {
191         case LPQ_QUEUED:
192                 return 0;
193         case LPQ_PAUSED:
194                 return JOB_STATUS_PAUSED;
195         case LPQ_SPOOLING:
196                 return JOB_STATUS_SPOOLING;
197         case LPQ_PRINTING:
198                 return JOB_STATUS_PRINTING;
199         case LPQ_ERROR:
200                 return JOB_STATUS_ERROR;
201         case LPQ_DELETING:
202                 return JOB_STATUS_DELETING;
203         case LPQ_OFFLINE:
204                 return JOB_STATUS_OFFLINE;
205         case LPQ_PAPEROUT:
206                 return JOB_STATUS_PAPEROUT;
207         case LPQ_PRINTED:
208                 return JOB_STATUS_PRINTED;
209         case LPQ_DELETED:
210                 return JOB_STATUS_DELETED;
211         case LPQ_BLOCKED:
212                 return JOB_STATUS_BLOCKED_DEVQ;
213         case LPQ_USER_INTERVENTION:
214                 return JOB_STATUS_USER_INTERVENTION;
215         }
216         return 0;
217 }
218
219 static int nt_printq_status(int v)
220 {
221         switch (v) {
222         case LPQ_PAUSED:
223                 return PRINTER_STATUS_PAUSED;
224         case LPQ_QUEUED:
225         case LPQ_SPOOLING:
226         case LPQ_PRINTING:
227                 return 0;
228         }
229         return 0;
230 }
231
232 /***************************************************************************
233  Disconnect from the client
234 ****************************************************************************/
235
236 static void srv_spoolss_replycloseprinter(int snum,
237                                           struct printer_handle *prn_hnd)
238 {
239         WERROR result;
240         NTSTATUS status;
241
242         /*
243          * Tell the specific printing tdb we no longer want messages for this printer
244          * by deregistering our PID.
245          */
246
247         if (!print_notify_deregister_pid(snum)) {
248                 DEBUG(0, ("Failed to register our pid for printer %s\n",
249                           lp_const_servicename(snum)));
250         }
251
252         /* weird if the test succeeds !!! */
253         if (prn_hnd->notify.cli_chan == NULL ||
254             prn_hnd->notify.cli_chan->active_connections == 0) {
255                 DEBUG(0, ("Trying to close unexisting backchannel!\n"));
256                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
257                 TALLOC_FREE(prn_hnd->notify.cli_chan);
258                 return;
259         }
260
261         status = dcerpc_spoolss_ReplyClosePrinter(
262                                         prn_hnd->notify.cli_chan->binding_handle,
263                                         talloc_tos(),
264                                         &prn_hnd->notify.cli_hnd,
265                                         &result);
266         if (!NT_STATUS_IS_OK(status)) {
267                 DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
268                           nt_errstr(status)));
269                 result = ntstatus_to_werror(status);
270         } else if (!W_ERROR_IS_OK(result)) {
271                 DEBUG(0, ("reply_close_printer failed [%s].\n",
272                           win_errstr(result)));
273         }
274
275         /* if it's the last connection, deconnect the IPC$ share */
276         if (prn_hnd->notify.cli_chan->active_connections == 1) {
277
278                 prn_hnd->notify.cli_chan->binding_handle = NULL;
279                 cli_shutdown(rpc_pipe_np_smb_conn(prn_hnd->notify.cli_chan->cli_pipe));
280                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
281                 TALLOC_FREE(prn_hnd->notify.cli_chan);
282
283                 if (prn_hnd->notify.msg_ctx != NULL) {
284                         messaging_deregister(prn_hnd->notify.msg_ctx,
285                                              MSG_PRINTER_NOTIFY2, NULL);
286
287                         /*
288                          * Tell the serverid.tdb we're no longer
289                          * interested in printer notify messages.
290                          */
291
292                         serverid_register_msg_flags(
293                                 messaging_server_id(prn_hnd->notify.msg_ctx),
294                                 false, FLAG_MSG_PRINT_NOTIFY);
295                 }
296         }
297
298         if (prn_hnd->notify.cli_chan) {
299                 prn_hnd->notify.cli_chan->active_connections--;
300         }
301 }
302
303 /****************************************************************************
304  Functions to free a printer entry datastruct.
305 ****************************************************************************/
306
307 static int printer_entry_destructor(struct printer_handle *Printer)
308 {
309         if (Printer->notify.cli_chan != NULL &&
310             Printer->notify.cli_chan->active_connections > 0) {
311                 int snum = -1;
312
313                 switch(Printer->printer_type) {
314                 case SPLHND_SERVER:
315                         srv_spoolss_replycloseprinter(snum, Printer);
316                         break;
317
318                 case SPLHND_PRINTER:
319                         snum = print_queue_snum(Printer->sharename);
320                         if (snum != -1) {
321                                 srv_spoolss_replycloseprinter(snum, Printer);
322                         }
323                         break;
324                 default:
325                         break;
326                 }
327         }
328
329         Printer->notify.flags=0;
330         Printer->notify.options=0;
331         Printer->notify.localmachine[0]='\0';
332         Printer->notify.printerlocal=0;
333         TALLOC_FREE(Printer->notify.option);
334         TALLOC_FREE(Printer->devmode);
335
336         /* Remove from the internal list. */
337         DLIST_REMOVE(printers_list, Printer);
338         return 0;
339 }
340
341 /****************************************************************************
342   find printer index by handle
343 ****************************************************************************/
344
345 static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
346                                                         struct policy_handle *hnd)
347 {
348         struct printer_handle *find_printer = NULL;
349
350         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
351                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
352                 return NULL;
353         }
354
355         return find_printer;
356 }
357
358 /****************************************************************************
359  Close printer index by handle.
360 ****************************************************************************/
361
362 static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
363 {
364         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
365
366         if (!Printer) {
367                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
368                         OUR_HANDLE(hnd)));
369                 return false;
370         }
371
372         close_policy_hnd(p, hnd);
373
374         return true;
375 }
376
377 /****************************************************************************
378  Delete a printer given a handle.
379 ****************************************************************************/
380
381 static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
382                                   const char *sharename,
383                                   struct messaging_context *msg_ctx)
384 {
385         char *cmd = lp_deleteprinter_cmd();
386         char *command = NULL;
387         int ret;
388         bool is_print_op = false;
389
390         /* can't fail if we don't try */
391
392         if ( !*cmd )
393                 return WERR_OK;
394
395         command = talloc_asprintf(ctx,
396                         "%s \"%s\"",
397                         cmd, sharename);
398         if (!command) {
399                 return WERR_NOMEM;
400         }
401         if ( token )
402                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
403
404         DEBUG(10,("Running [%s]\n", command));
405
406         /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
407
408         if ( is_print_op )
409                 become_root();
410
411         if ( (ret = smbrun(command, NULL)) == 0 ) {
412                 /* Tell everyone we updated smb.conf. */
413                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
414         }
415
416         if ( is_print_op )
417                 unbecome_root();
418
419         /********** END SePrintOperatorPrivlege BLOCK **********/
420
421         DEBUGADD(10,("returned [%d]\n", ret));
422
423         TALLOC_FREE(command);
424
425         if (ret != 0)
426                 return WERR_BADFID; /* What to return here? */
427
428         /* go ahead and re-read the services immediately */
429         become_root();
430         reload_services(msg_ctx, -1, false);
431         unbecome_root();
432
433         if ( lp_servicenumber( sharename ) >= 0 )
434                 return WERR_ACCESS_DENIED;
435
436         return WERR_OK;
437 }
438
439 /****************************************************************************
440  Delete a printer given a handle.
441 ****************************************************************************/
442
443 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
444 {
445         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
446         WERROR result;
447
448         if (!Printer) {
449                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
450                         OUR_HANDLE(hnd)));
451                 return WERR_BADFID;
452         }
453
454         /*
455          * It turns out that Windows allows delete printer on a handle
456          * opened by an admin user, then used on a pipe handle created
457          * by an anonymous user..... but they're working on security.... riiight !
458          * JRA.
459          */
460
461         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
462                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
463                 return WERR_ACCESS_DENIED;
464         }
465
466         /* this does not need a become root since the access check has been
467            done on the handle already */
468
469         result = winreg_delete_printer_key_internal(p->mem_ctx,
470                                            get_session_info_system(),
471                                            p->msg_ctx,
472                                            Printer->sharename,
473                                            "");
474         if (!W_ERROR_IS_OK(result)) {
475                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
476                 return WERR_BADFID;
477         }
478
479         result = delete_printer_hook(p->mem_ctx, p->session_info->security_token,
480                                      Printer->sharename, p->msg_ctx);
481         if (!W_ERROR_IS_OK(result)) {
482                 return result;
483         }
484         prune_printername_cache();
485         return WERR_OK;
486 }
487
488 /****************************************************************************
489  Return the snum of a printer corresponding to an handle.
490 ****************************************************************************/
491
492 static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
493                              int *number, struct share_params **params)
494 {
495         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
496
497         if (!Printer) {
498                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
499                         OUR_HANDLE(hnd)));
500                 return false;
501         }
502
503         switch (Printer->printer_type) {
504                 case SPLHND_PRINTER:
505                         DEBUG(4,("short name:%s\n", Printer->sharename));
506                         *number = print_queue_snum(Printer->sharename);
507                         return (*number != -1);
508                 case SPLHND_SERVER:
509                         return false;
510                 default:
511                         return false;
512         }
513 }
514
515 /****************************************************************************
516  Set printer handle type.
517  Check if it's \\server or \\server\printer
518 ****************************************************************************/
519
520 static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
521 {
522         DEBUG(3,("Setting printer type=%s\n", handlename));
523
524         /* it's a print server */
525         if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
526                 DEBUGADD(4,("Printer is a print server\n"));
527                 Printer->printer_type = SPLHND_SERVER;
528         }
529         /* it's a printer (set_printer_hnd_name() will handle port monitors */
530         else {
531                 DEBUGADD(4,("Printer is a printer\n"));
532                 Printer->printer_type = SPLHND_PRINTER;
533         }
534
535         return true;
536 }
537
538 static void prune_printername_cache_fn(const char *key, const char *value,
539                                        time_t timeout, void *private_data)
540 {
541         gencache_del(key);
542 }
543
544 static void prune_printername_cache(void)
545 {
546         gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
547 }
548
549 /****************************************************************************
550  Set printer handle name..  Accept names like \\server, \\server\printer,
551  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
552  the MSDN docs regarding OpenPrinter() for details on the XcvData() and
553  XcvDataPort() interface.
554 ****************************************************************************/
555
556 static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
557                                    const struct auth_serversupplied_info *session_info,
558                                    struct messaging_context *msg_ctx,
559                                    struct printer_handle *Printer,
560                                    const char *handlename)
561 {
562         int snum;
563         int n_services=lp_numservices();
564         char *aprinter;
565         const char *printername;
566         const char *servername = NULL;
567         fstring sname;
568         bool found = false;
569         struct spoolss_PrinterInfo2 *info2 = NULL;
570         WERROR result;
571         char *p;
572
573         /*
574          * Hopefully nobody names his printers like this. Maybe \ or ,
575          * are illegal in printer names even?
576          */
577         const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
578         char *cache_key;
579         char *tmp;
580
581         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
582                 (unsigned long)strlen(handlename)));
583
584         aprinter = discard_const_p(char, handlename);
585         if ( *handlename == '\\' ) {
586                 servername = canon_servername(handlename);
587                 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
588                         *aprinter = '\0';
589                         aprinter++;
590                 }
591                 if (!is_myname_or_ipaddr(servername)) {
592                         return WERR_INVALID_PRINTER_NAME;
593                 }
594                 Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
595                 if (Printer->servername == NULL) {
596                         return WERR_NOMEM;
597                 }
598         }
599
600         if (Printer->printer_type == SPLHND_SERVER) {
601                 return WERR_OK;
602         }
603
604         if (Printer->printer_type != SPLHND_PRINTER) {
605                 return WERR_INVALID_HANDLE;
606         }
607
608         DEBUGADD(5, ("searching for [%s]\n", aprinter));
609
610         p = strchr(aprinter, ',');
611         if (p != NULL) {
612                 char *p2 = p;
613                 p++;
614                 if (*p == ' ') {
615                         p++;
616                 }
617                 if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
618                         *p2 = '\0';
619                 } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
620                         *p2 = '\0';
621                 }
622         }
623
624         if (p) {
625                 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
626         }
627
628         /* check for the Port Monitor Interface */
629         if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
630                 Printer->printer_type = SPLHND_PORTMON_TCP;
631                 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
632                 found = true;
633         }
634         else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
635                 Printer->printer_type = SPLHND_PORTMON_LOCAL;
636                 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
637                 found = true;
638         }
639
640         /*
641          * With hundreds of printers, the "for" loop iterating all
642          * shares can be quite expensive, as it is done on every
643          * OpenPrinter. The loop maps "aprinter" to "sname", the
644          * result of which we cache in gencache.
645          */
646
647         cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s",
648                                     aprinter);
649         if ((cache_key != NULL) && gencache_get(cache_key, &tmp, NULL)) {
650
651                 found = (strcmp(tmp, printer_not_found) != 0);
652                 if (!found) {
653                         DEBUG(4, ("Printer %s not found\n", aprinter));
654                         SAFE_FREE(tmp);
655                         return WERR_INVALID_PRINTER_NAME;
656                 }
657                 fstrcpy(sname, tmp);
658                 SAFE_FREE(tmp);
659         }
660
661         /* Search all sharenames first as this is easier than pulling
662            the printer_info_2 off of disk. Don't use find_service() since
663            that calls out to map_username() */
664
665         /* do another loop to look for printernames */
666         for (snum = 0; !found && snum < n_services; snum++) {
667                 const char *printer = lp_const_servicename(snum);
668
669                 /* no point going on if this is not a printer */
670                 if (!(lp_snum_ok(snum) && lp_print_ok(snum))) {
671                         continue;
672                 }
673
674                 /* ignore [printers] share */
675                 if (strequal(printer, "printers")) {
676                         continue;
677                 }
678
679                 fstrcpy(sname, printer);
680                 if (strequal(aprinter, printer)) {
681                         found = true;
682                         break;
683                 }
684
685                 /* no point looking up the printer object if
686                    we aren't allowing printername != sharename */
687                 if (lp_force_printername(snum)) {
688                         continue;
689                 }
690
691                 result = winreg_get_printer_internal(mem_ctx,
692                                             session_info,
693                                             msg_ctx,
694                                             sname,
695                                             &info2);
696                 if ( !W_ERROR_IS_OK(result) ) {
697                         DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
698                                  sname, win_errstr(result)));
699                         continue;
700                 }
701
702                 printername = strrchr(info2->printername, '\\');
703                 if (printername == NULL) {
704                         printername = info2->printername;
705                 } else {
706                         printername++;
707                 }
708
709                 if (strequal(printername, aprinter)) {
710                         found = true;
711                         break;
712                 }
713
714                 DEBUGADD(10, ("printername: %s\n", printername));
715
716                 TALLOC_FREE(info2);
717         }
718
719         if ( !found ) {
720                 if (cache_key != NULL) {
721                         gencache_set(cache_key, printer_not_found,
722                                      time(NULL)+300);
723                         TALLOC_FREE(cache_key);
724                 }
725                 DEBUGADD(4,("Printer not found\n"));
726                 return WERR_INVALID_PRINTER_NAME;
727         }
728
729         if (cache_key != NULL) {
730                 gencache_set(cache_key, sname, time(NULL)+300);
731                 TALLOC_FREE(cache_key);
732         }
733
734         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
735
736         strlcpy(Printer->sharename, sname, sizeof(Printer->sharename));
737
738         return WERR_OK;
739 }
740
741 /****************************************************************************
742  Find first available printer slot. creates a printer handle for you.
743  ****************************************************************************/
744
745 static WERROR open_printer_hnd(struct pipes_struct *p,
746                                struct policy_handle *hnd,
747                                const char *name,
748                                uint32_t access_granted)
749 {
750         struct printer_handle *new_printer;
751         WERROR result;
752
753         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
754
755         new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
756         if (new_printer == NULL) {
757                 return WERR_NOMEM;
758         }
759         talloc_set_destructor(new_printer, printer_entry_destructor);
760
761         /* This also steals the printer_handle on the policy_handle */
762         if (!create_policy_hnd(p, hnd, new_printer)) {
763                 TALLOC_FREE(new_printer);
764                 return WERR_INVALID_HANDLE;
765         }
766
767         /* Add to the internal list. */
768         DLIST_ADD(printers_list, new_printer);
769
770         new_printer->notify.option=NULL;
771
772         if (!set_printer_hnd_printertype(new_printer, name)) {
773                 close_printer_handle(p, hnd);
774                 return WERR_INVALID_HANDLE;
775         }
776
777         result = set_printer_hnd_name(p->mem_ctx,
778                                       get_session_info_system(),
779                                       p->msg_ctx,
780                                       new_printer, name);
781         if (!W_ERROR_IS_OK(result)) {
782                 close_printer_handle(p, hnd);
783                 return result;
784         }
785
786         new_printer->access_granted = access_granted;
787
788         DEBUG(5, ("%d printer handles active\n",
789                   (int)num_pipe_handles(p)));
790
791         return WERR_OK;
792 }
793
794 /***************************************************************************
795  check to see if the client motify handle is monitoring the notification
796  given by (notify_type, notify_field).
797  **************************************************************************/
798
799 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
800                                       uint16_t notify_field)
801 {
802         return true;
803 }
804
805 static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
806                                 uint16_t notify_field)
807 {
808         struct spoolss_NotifyOption *option = p->notify.option;
809         uint32_t i, j;
810
811         /*
812          * Flags should always be zero when the change notify
813          * is registered by the client's spooler.  A user Win32 app
814          * might use the flags though instead of the NOTIFY_OPTION_INFO
815          * --jerry
816          */
817
818         if (!option) {
819                 return false;
820         }
821
822         if (p->notify.flags)
823                 return is_monitoring_event_flags(
824                         p->notify.flags, notify_type, notify_field);
825
826         for (i = 0; i < option->count; i++) {
827
828                 /* Check match for notify_type */
829
830                 if (option->types[i].type != notify_type)
831                         continue;
832
833                 /* Check match for field */
834
835                 for (j = 0; j < option->types[i].count; j++) {
836                         if (option->types[i].fields[j].field == notify_field) {
837                                 return true;
838                         }
839                 }
840         }
841
842         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
843                    p->servername, p->sharename, notify_type, notify_field));
844
845         return false;
846 }
847
848 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
849         _data->data.integer[0] = _integer; \
850         _data->data.integer[1] = 0;
851
852
853 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
854         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
855         if (!_data->data.string.string) {\
856                 _data->data.string.size = 0; \
857         } \
858         _data->data.string.size = strlen_m_term(_p) * 2;
859
860 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
861         _data->data.devmode.devmode = _devmode;
862
863 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
864         _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
865         if (!_data->data.sd.sd) { \
866                 _data->data.sd.sd_size = 0; \
867         } \
868         _data->data.sd.sd_size = \
869                 ndr_size_security_descriptor(_data->data.sd.sd, 0);
870
871 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
872                                    struct tm *t,
873                                    const char **pp,
874                                    uint32_t *plen)
875 {
876         struct spoolss_Time st;
877         uint32_t len = 16;
878         char *p;
879
880         if (!init_systemtime(&st, t)) {
881                 return;
882         }
883
884         p = talloc_array(mem_ctx, char, len);
885         if (!p) {
886                 return;
887         }
888
889         /*
890          * Systemtime must be linearized as a set of UINT16's.
891          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
892          */
893
894         SSVAL(p, 0, st.year);
895         SSVAL(p, 2, st.month);
896         SSVAL(p, 4, st.day_of_week);
897         SSVAL(p, 6, st.day);
898         SSVAL(p, 8, st.hour);
899         SSVAL(p, 10, st.minute);
900         SSVAL(p, 12, st.second);
901         SSVAL(p, 14, st.millisecond);
902
903         *pp = p;
904         *plen = len;
905 }
906
907 /* Convert a notification message to a struct spoolss_Notify */
908
909 static void notify_one_value(struct spoolss_notify_msg *msg,
910                              struct spoolss_Notify *data,
911                              TALLOC_CTX *mem_ctx)
912 {
913         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
914 }
915
916 static void notify_string(struct spoolss_notify_msg *msg,
917                           struct spoolss_Notify *data,
918                           TALLOC_CTX *mem_ctx)
919 {
920         /* The length of the message includes the trailing \0 */
921
922         data->data.string.size = msg->len * 2;
923         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
924         if (!data->data.string.string) {
925                 data->data.string.size = 0;
926                 return;
927         }
928 }
929
930 static void notify_system_time(struct spoolss_notify_msg *msg,
931                                struct spoolss_Notify *data,
932                                TALLOC_CTX *mem_ctx)
933 {
934         data->data.string.string = NULL;
935         data->data.string.size = 0;
936
937         if (msg->len != sizeof(time_t)) {
938                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
939                           msg->len));
940                 return;
941         }
942
943         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
944                                &data->data.string.string,
945                                &data->data.string.size);
946 }
947
948 struct notify2_message_table {
949         const char *name;
950         void (*fn)(struct spoolss_notify_msg *msg,
951                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
952 };
953
954 static struct notify2_message_table printer_notify_table[] = {
955         /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
956         /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
957         /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
958         /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
959         /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
960         /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
961         /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
962         /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
963         /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
964         /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
965         /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
966         /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
967         /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
968         /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
969         /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
970         /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
971         /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
972         /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
973         /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
974 };
975
976 static struct notify2_message_table job_notify_table[] = {
977         /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
978         /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
979         /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
980         /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
981         /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
982         /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
983         /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
984         /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
985         /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
986         /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
987         /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
988         /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
989         /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
990         /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
991         /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
992         /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
993         /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
994         /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
995         /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
996         /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
997         /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
998         /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
999         /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
1000         /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
1001 };
1002
1003
1004 /***********************************************************************
1005  Allocate talloc context for container object
1006  **********************************************************************/
1007
1008 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1009 {
1010         if ( !ctr )
1011                 return;
1012
1013         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
1014
1015         return;
1016 }
1017
1018 /***********************************************************************
1019  release all allocated memory and zero out structure
1020  **********************************************************************/
1021
1022 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1023 {
1024         if ( !ctr )
1025                 return;
1026
1027         if ( ctr->ctx )
1028                 talloc_destroy(ctr->ctx);
1029
1030         ZERO_STRUCTP(ctr);
1031
1032         return;
1033 }
1034
1035 /***********************************************************************
1036  **********************************************************************/
1037
1038 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1039 {
1040         if ( !ctr )
1041                 return NULL;
1042
1043         return ctr->ctx;
1044 }
1045
1046 /***********************************************************************
1047  **********************************************************************/
1048
1049 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1050 {
1051         if ( !ctr || !ctr->msg_groups )
1052                 return NULL;
1053
1054         if ( idx >= ctr->num_groups )
1055                 return NULL;
1056
1057         return &ctr->msg_groups[idx];
1058
1059 }
1060
1061 /***********************************************************************
1062  How many groups of change messages do we have ?
1063  **********************************************************************/
1064
1065 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1066 {
1067         if ( !ctr )
1068                 return 0;
1069
1070         return ctr->num_groups;
1071 }
1072
1073 /***********************************************************************
1074  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1075  **********************************************************************/
1076
1077 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1078 {
1079         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
1080         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
1081         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
1082         int                             i, new_slot;
1083
1084         if ( !ctr || !msg )
1085                 return 0;
1086
1087         /* loop over all groups looking for a matching printer name */
1088
1089         for ( i=0; i<ctr->num_groups; i++ ) {
1090                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1091                         break;
1092         }
1093
1094         /* add a new group? */
1095
1096         if ( i == ctr->num_groups ) {
1097                 ctr->num_groups++;
1098
1099                 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1100                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1101                         return 0;
1102                 }
1103                 ctr->msg_groups = groups;
1104
1105                 /* clear the new entry and set the printer name */
1106
1107                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1108                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1109         }
1110
1111         /* add the change messages; 'i' is the correct index now regardless */
1112
1113         msg_grp = &ctr->msg_groups[i];
1114
1115         msg_grp->num_msgs++;
1116
1117         if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1118                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1119                 return 0;
1120         }
1121         msg_grp->msgs = msg_list;
1122
1123         new_slot = msg_grp->num_msgs-1;
1124         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1125
1126         /* need to allocate own copy of data */
1127
1128         if ( msg->len != 0 )
1129                 msg_grp->msgs[new_slot].notify.data = (char *)
1130                         talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
1131
1132         return ctr->num_groups;
1133 }
1134
1135 static void construct_info_data(struct spoolss_Notify *info_data,
1136                                 enum spoolss_NotifyType type,
1137                                 uint16_t field, int id);
1138
1139 /***********************************************************************
1140  Send a change notication message on all handles which have a call
1141  back registered
1142  **********************************************************************/
1143
1144 static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1145                                   struct printer_handle *prn_hnd,
1146                                   SPOOLSS_NOTIFY_MSG *messages,
1147                                   uint32_t num_msgs,
1148                                   struct spoolss_Notify **_notifies,
1149                                   int *_count)
1150 {
1151         struct spoolss_Notify *notifies;
1152         SPOOLSS_NOTIFY_MSG *msg;
1153         int count = 0;
1154         uint32_t id;
1155         int i;
1156
1157         notifies = talloc_zero_array(mem_ctx,
1158                                      struct spoolss_Notify, num_msgs);
1159         if (!notifies) {
1160                 return ENOMEM;
1161         }
1162
1163         for (i = 0; i < num_msgs; i++) {
1164
1165                 msg = &messages[i];
1166
1167                 /* Are we monitoring this event? */
1168
1169                 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1170                         continue;
1171                 }
1172
1173                 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1174                            "for printer [%s]\n",
1175                            msg->type, msg->field, prn_hnd->sharename));
1176
1177                 /*
1178                  * if the is a printer notification handle and not a job
1179                  * notification type, then set the id to 0.
1180                  * Otherwise just use what was specified in the message.
1181                  *
1182                  * When registering change notification on a print server
1183                  * handle we always need to send back the id (snum) matching
1184                  * the printer for which the change took place.
1185                  * For change notify registered on a printer handle,
1186                  * this does not matter and the id should be 0.
1187                  *
1188                  * --jerry
1189                  */
1190
1191                 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1192                     (prn_hnd->printer_type == SPLHND_PRINTER)) {
1193                         id = 0;
1194                 } else {
1195                         id = msg->id;
1196                 }
1197
1198                 /* Convert unix jobid to smb jobid */
1199
1200                 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1201                         id = sysjob_to_jobid(msg->id);
1202
1203                         if (id == -1) {
1204                                 DEBUG(3, ("no such unix jobid %d\n",
1205                                           msg->id));
1206                                 continue;
1207                         }
1208                 }
1209
1210                 construct_info_data(&notifies[count],
1211                                     msg->type, msg->field, id);
1212
1213                 switch(msg->type) {
1214                 case PRINTER_NOTIFY_TYPE:
1215                         if (printer_notify_table[msg->field].fn) {
1216                                 printer_notify_table[msg->field].fn(msg,
1217                                                 &notifies[count], mem_ctx);
1218                         }
1219                         break;
1220
1221                 case JOB_NOTIFY_TYPE:
1222                         if (job_notify_table[msg->field].fn) {
1223                                 job_notify_table[msg->field].fn(msg,
1224                                                 &notifies[count], mem_ctx);
1225                         }
1226                         break;
1227
1228                 default:
1229                         DEBUG(5, ("Unknown notification type %d\n",
1230                                   msg->type));
1231                         continue;
1232                 }
1233
1234                 count++;
1235         }
1236
1237         *_notifies = notifies;
1238         *_count = count;
1239
1240         return 0;
1241 }
1242
1243 static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1244                                 struct printer_handle *prn_hnd,
1245                                 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1246 {
1247         struct spoolss_Notify *notifies;
1248         int count = 0;
1249         union spoolss_ReplyPrinterInfo info;
1250         struct spoolss_NotifyInfo info0;
1251         uint32_t reply_result;
1252         NTSTATUS status;
1253         WERROR werr;
1254         int ret;
1255
1256         /* Is there notification on this handle? */
1257         if (prn_hnd->notify.cli_chan == NULL ||
1258             prn_hnd->notify.cli_chan->active_connections == 0) {
1259                 return 0;
1260         }
1261
1262         DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1263                    prn_hnd->servername, prn_hnd->sharename));
1264
1265         /* For this printer? Print servers always receive notifications. */
1266         if ((prn_hnd->printer_type == SPLHND_PRINTER)  &&
1267             (!strequal(msg_group->printername, prn_hnd->sharename))) {
1268                 return 0;
1269         }
1270
1271         DEBUG(10,("Our printer\n"));
1272
1273         /* build the array of change notifications */
1274         ret = build_notify2_messages(mem_ctx, prn_hnd,
1275                                      msg_group->msgs,
1276                                      msg_group->num_msgs,
1277                                      &notifies, &count);
1278         if (ret) {
1279                 return ret;
1280         }
1281
1282         info0.version   = 0x2;
1283         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1284         info0.count     = count;
1285         info0.notifies  = notifies;
1286
1287         info.info0 = &info0;
1288
1289         status = dcerpc_spoolss_RouterReplyPrinterEx(
1290                                 prn_hnd->notify.cli_chan->binding_handle,
1291                                 mem_ctx,
1292                                 &prn_hnd->notify.cli_hnd,
1293                                 prn_hnd->notify.change, /* color */
1294                                 prn_hnd->notify.flags,
1295                                 &reply_result,
1296                                 0, /* reply_type, must be 0 */
1297                                 info, &werr);
1298         if (!NT_STATUS_IS_OK(status)) {
1299                 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1300                           "failed: %s\n",
1301                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1302                           nt_errstr(status)));
1303                 werr = ntstatus_to_werror(status);
1304         } else if (!W_ERROR_IS_OK(werr)) {
1305                 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1306                           "failed: %s\n",
1307                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1308                           win_errstr(werr)));
1309         }
1310         switch (reply_result) {
1311         case 0:
1312                 break;
1313         case PRINTER_NOTIFY_INFO_DISCARDED:
1314         case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1315         case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1316                 break;
1317         default:
1318                 break;
1319         }
1320
1321         return 0;
1322 }
1323
1324 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1325 {
1326         struct printer_handle    *p;
1327         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
1328         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1329         int ret;
1330
1331         if ( !msg_group ) {
1332                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1333                 return;
1334         }
1335
1336         if (!msg_group->msgs) {
1337                 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1338                 return;
1339         }
1340
1341         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1342
1343         /* loop over all printers */
1344
1345         for (p = printers_list; p; p = p->next) {
1346                 ret = send_notify2_printer(mem_ctx, p, msg_group);
1347                 if (ret) {
1348                         goto done;
1349                 }
1350         }
1351
1352 done:
1353         DEBUG(8,("send_notify2_changes: Exit...\n"));
1354         return;
1355 }
1356
1357 /***********************************************************************
1358  **********************************************************************/
1359
1360 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1361 {
1362
1363         uint32_t tv_sec, tv_usec;
1364         size_t offset = 0;
1365
1366         /* Unpack message */
1367
1368         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1369                              msg->printer);
1370
1371         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1372                                 &tv_sec, &tv_usec,
1373                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1374
1375         if (msg->len == 0)
1376                 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1377                            &msg->notify.value[0], &msg->notify.value[1]);
1378         else
1379                 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1380                            &msg->len, &msg->notify.data);
1381
1382         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1383                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1384
1385         tv->tv_sec = tv_sec;
1386         tv->tv_usec = tv_usec;
1387
1388         if (msg->len == 0)
1389                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1390                           msg->notify.value[1]));
1391         else
1392                 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1393
1394         return true;
1395 }
1396
1397 /********************************************************************
1398  Receive a notify2 message list
1399  ********************************************************************/
1400
1401 static void receive_notify2_message_list(struct messaging_context *msg,
1402                                          void *private_data,
1403                                          uint32_t msg_type,
1404                                          struct server_id server_id,
1405                                          DATA_BLOB *data)
1406 {
1407         size_t                  msg_count, i;
1408         char                    *buf = (char *)data->data;
1409         char                    *msg_ptr;
1410         size_t                  msg_len;
1411         SPOOLSS_NOTIFY_MSG      notify;
1412         SPOOLSS_NOTIFY_MSG_CTR  messages;
1413         int                     num_groups;
1414
1415         if (data->length < 4) {
1416                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1417                 return;
1418         }
1419
1420         msg_count = IVAL(buf, 0);
1421         msg_ptr = buf + 4;
1422
1423         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1424
1425         if (msg_count == 0) {
1426                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1427                 return;
1428         }
1429
1430         /* initialize the container */
1431
1432         ZERO_STRUCT( messages );
1433         notify_msg_ctr_init( &messages );
1434
1435         /*
1436          * build message groups for each printer identified
1437          * in a change_notify msg.  Remember that a PCN message
1438          * includes the handle returned for the srv_spoolss_replyopenprinter()
1439          * call.  Therefore messages are grouped according to printer handle.
1440          */
1441
1442         for ( i=0; i<msg_count; i++ ) {
1443                 struct timeval msg_tv;
1444
1445                 if (msg_ptr + 4 - buf > data->length) {
1446                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1447                         return;
1448                 }
1449
1450                 msg_len = IVAL(msg_ptr,0);
1451                 msg_ptr += 4;
1452
1453                 if (msg_ptr + msg_len - buf > data->length) {
1454                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1455                         return;
1456                 }
1457
1458                 /* unpack messages */
1459
1460                 ZERO_STRUCT( notify );
1461                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1462                 msg_ptr += msg_len;
1463
1464                 /* add to correct list in container */
1465
1466                 notify_msg_ctr_addmsg( &messages, &notify );
1467
1468                 /* free memory that might have been allocated by notify2_unpack_msg() */
1469
1470                 if ( notify.len != 0 )
1471                         SAFE_FREE( notify.notify.data );
1472         }
1473
1474         /* process each group of messages */
1475
1476         num_groups = notify_msg_ctr_numgroups( &messages );
1477         for ( i=0; i<num_groups; i++ )
1478                 send_notify2_changes( &messages, i );
1479
1480
1481         /* cleanup */
1482
1483         DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1484                 (uint32_t)msg_count ));
1485
1486         notify_msg_ctr_destroy( &messages );
1487
1488         return;
1489 }
1490
1491 /********************************************************************
1492  Send a message to ourself about new driver being installed
1493  so we can upgrade the information for each printer bound to this
1494  driver
1495  ********************************************************************/
1496
1497 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1498                                             struct messaging_context *msg_ctx)
1499 {
1500         int len = strlen(drivername);
1501
1502         if (!len)
1503                 return false;
1504
1505         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1506                 drivername));
1507
1508         messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1509                            MSG_PRINTER_DRVUPGRADE,
1510                            (const uint8_t *)drivername, len+1);
1511
1512         return true;
1513 }
1514
1515 void srv_spoolss_cleanup(void)
1516 {
1517         struct printer_session_counter *session_counter;
1518
1519         for (session_counter = counter_list;
1520              session_counter != NULL;
1521              session_counter = counter_list) {
1522                 DLIST_REMOVE(counter_list, session_counter);
1523                 TALLOC_FREE(session_counter);
1524         }
1525 }
1526
1527 /**********************************************************************
1528  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1529  over all printers, upgrading ones as necessary
1530  **********************************************************************/
1531
1532 void do_drv_upgrade_printer(struct messaging_context *msg,
1533                             void *private_data,
1534                             uint32_t msg_type,
1535                             struct server_id server_id,
1536                             DATA_BLOB *data)
1537 {
1538         TALLOC_CTX *tmp_ctx;
1539         struct auth_serversupplied_info *session_info = NULL;
1540         struct spoolss_PrinterInfo2 *pinfo2;
1541         NTSTATUS status;
1542         WERROR result;
1543         const char *drivername;
1544         int snum;
1545         int n_services = lp_numservices();
1546         struct dcerpc_binding_handle *b = NULL;
1547
1548         tmp_ctx = talloc_new(NULL);
1549         if (!tmp_ctx) return;
1550
1551         status = make_session_info_system(tmp_ctx, &session_info);
1552         if (!NT_STATUS_IS_OK(status)) {
1553                 DEBUG(0, ("do_drv_upgrade_printer: "
1554                           "Could not create system session_info\n"));
1555                 goto done;
1556         }
1557
1558         drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1559         if (!drivername) {
1560                 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1561                 goto done;
1562         }
1563
1564         DEBUG(10, ("do_drv_upgrade_printer: "
1565                    "Got message for new driver [%s]\n", drivername));
1566
1567         /* Iterate the printer list */
1568
1569         for (snum = 0; snum < n_services; snum++) {
1570                 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1571                         continue;
1572                 }
1573
1574                 /* ignore [printers] share */
1575                 if (strequal(lp_const_servicename(snum), "printers")) {
1576                         continue;
1577                 }
1578
1579                 if (b == NULL) {
1580                         result = winreg_printer_binding_handle(tmp_ctx,
1581                                                                session_info,
1582                                                                msg,
1583                                                                &b);
1584                         if (!W_ERROR_IS_OK(result)) {
1585                                 break;
1586                         }
1587                 }
1588
1589                 result = winreg_get_printer(tmp_ctx, b,
1590                                             lp_const_servicename(snum),
1591                                             &pinfo2);
1592
1593                 if (!W_ERROR_IS_OK(result)) {
1594                         continue;
1595                 }
1596
1597                 if (!pinfo2->drivername) {
1598                         continue;
1599                 }
1600
1601                 if (strcmp(drivername, pinfo2->drivername) != 0) {
1602                         continue;
1603                 }
1604
1605                 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1606
1607                 /* all we care about currently is the change_id */
1608                 result = winreg_printer_update_changeid(tmp_ctx, b,
1609                                                         pinfo2->printername);
1610
1611                 if (!W_ERROR_IS_OK(result)) {
1612                         DEBUG(3, ("do_drv_upgrade_printer: "
1613                                   "Failed to update changeid [%s]\n",
1614                                   win_errstr(result)));
1615                 }
1616         }
1617
1618         /* all done */
1619 done:
1620         talloc_free(tmp_ctx);
1621 }
1622
1623 /********************************************************************
1624  Update the cache for all printq's with a registered client
1625  connection
1626  ********************************************************************/
1627
1628 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1629 {
1630         struct printer_handle *printer = printers_list;
1631         int snum;
1632
1633         /* loop through all printers and update the cache where
1634            a client is connected */
1635         while (printer) {
1636                 if ((printer->printer_type == SPLHND_PRINTER) &&
1637                     ((printer->notify.cli_chan != NULL) &&
1638                      (printer->notify.cli_chan->active_connections > 0))) {
1639                         snum = print_queue_snum(printer->sharename);
1640                         print_queue_status(msg_ctx, snum, NULL, NULL);
1641                 }
1642
1643                 printer = printer->next;
1644         }
1645
1646         return;
1647 }
1648
1649 /****************************************************************
1650  _spoolss_OpenPrinter
1651 ****************************************************************/
1652
1653 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1654                             struct spoolss_OpenPrinter *r)
1655 {
1656         struct spoolss_OpenPrinterEx e;
1657         WERROR werr;
1658
1659         ZERO_STRUCT(e.in.userlevel);
1660
1661         e.in.printername        = r->in.printername;
1662         e.in.datatype           = r->in.datatype;
1663         e.in.devmode_ctr        = r->in.devmode_ctr;
1664         e.in.access_mask        = r->in.access_mask;
1665         e.in.level              = 0;
1666
1667         e.out.handle            = r->out.handle;
1668
1669         werr = _spoolss_OpenPrinterEx(p, &e);
1670
1671         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1672                 /* OpenPrinterEx returns this for a bad
1673                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1674                  * instead.
1675                  */
1676                 werr = WERR_INVALID_PRINTER_NAME;
1677         }
1678
1679         return werr;
1680 }
1681
1682 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1683                               struct spoolss_DeviceMode *orig,
1684                               struct spoolss_DeviceMode **dest)
1685 {
1686         struct spoolss_DeviceMode *dm;
1687
1688         dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1689         if (!dm) {
1690                 return WERR_NOMEM;
1691         }
1692
1693         /* copy all values, then duplicate strings and structs */
1694         *dm = *orig;
1695
1696         dm->devicename = talloc_strdup(dm, orig->devicename);
1697         if (!dm->devicename) {
1698                 return WERR_NOMEM;
1699         }
1700         dm->formname = talloc_strdup(dm, orig->formname);
1701         if (!dm->formname) {
1702                 return WERR_NOMEM;
1703         }
1704         if (orig->driverextra_data.data) {
1705                 dm->driverextra_data.data =
1706                         (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1707                                         orig->driverextra_data.length);
1708                 if (!dm->driverextra_data.data) {
1709                         return WERR_NOMEM;
1710                 }
1711         }
1712
1713         *dest = dm;
1714         return WERR_OK;
1715 }
1716
1717 /****************************************************************
1718  _spoolss_OpenPrinterEx
1719 ****************************************************************/
1720
1721 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1722                               struct spoolss_OpenPrinterEx *r)
1723 {
1724         int snum;
1725         char *raddr;
1726         char *rhost;
1727         struct printer_handle *Printer=NULL;
1728         WERROR result;
1729         int rc;
1730
1731         if (!r->in.printername) {
1732                 return WERR_INVALID_PARAM;
1733         }
1734
1735         if (r->in.level > 3) {
1736                 return WERR_INVALID_PARAM;
1737         }
1738         if ((r->in.level == 1 && !r->in.userlevel.level1) ||
1739             (r->in.level == 2 && !r->in.userlevel.level2) ||
1740             (r->in.level == 3 && !r->in.userlevel.level3)) {
1741                 return WERR_INVALID_PARAM;
1742         }
1743
1744         /* some sanity check because you can open a printer or a print server */
1745         /* aka: \\server\printer or \\server */
1746
1747         DEBUGADD(3,("checking name: %s\n", r->in.printername));
1748
1749         result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1750         if (!W_ERROR_IS_OK(result)) {
1751                 DEBUG(0,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1752                         "for printer %s\n", r->in.printername));
1753                 ZERO_STRUCTP(r->out.handle);
1754                 return result;
1755         }
1756
1757         Printer = find_printer_index_by_hnd(p, r->out.handle);
1758         if ( !Printer ) {
1759                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1760                         "handle we created for printer %s\n", r->in.printername));
1761                 close_printer_handle(p, r->out.handle);
1762                 ZERO_STRUCTP(r->out.handle);
1763                 return WERR_INVALID_PARAM;
1764         }
1765
1766         /*
1767          * First case: the user is opening the print server:
1768          *
1769          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1770          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1771          *
1772          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1773          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1774          * or if the user is listed in the smb.conf printer admin parameter.
1775          *
1776          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1777          * client view printer folder, but does not show the MSAPW.
1778          *
1779          * Note: this test needs code to check access rights here too. Jeremy
1780          * could you look at this?
1781          *
1782          * Second case: the user is opening a printer:
1783          * NT doesn't let us connect to a printer if the connecting user
1784          * doesn't have print permission.
1785          *
1786          * Third case: user is opening a Port Monitor
1787          * access checks same as opening a handle to the print server.
1788          */
1789
1790         switch (Printer->printer_type )
1791         {
1792         case SPLHND_SERVER:
1793         case SPLHND_PORTMON_TCP:
1794         case SPLHND_PORTMON_LOCAL:
1795                 /* Printserver handles use global struct... */
1796
1797                 snum = -1;
1798
1799                 /* Map standard access rights to object specific access rights */
1800
1801                 se_map_standard(&r->in.access_mask,
1802                                 &printserver_std_mapping);
1803
1804                 /* Deny any object specific bits that don't apply to print
1805                    servers (i.e printer and job specific bits) */
1806
1807                 r->in.access_mask &= SEC_MASK_SPECIFIC;
1808
1809                 if (r->in.access_mask &
1810                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1811                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1812                         close_printer_handle(p, r->out.handle);
1813                         ZERO_STRUCTP(r->out.handle);
1814                         return WERR_ACCESS_DENIED;
1815                 }
1816
1817                 /* Allow admin access */
1818
1819                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1820                 {
1821                         if (!lp_ms_add_printer_wizard()) {
1822                                 close_printer_handle(p, r->out.handle);
1823                                 ZERO_STRUCTP(r->out.handle);
1824                                 return WERR_ACCESS_DENIED;
1825                         }
1826
1827                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1828                            and not a printer admin, then fail */
1829
1830                         if ((p->session_info->utok.uid != sec_initial_uid()) &&
1831                             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
1832                             !nt_token_check_sid(&global_sid_Builtin_Print_Operators, p->session_info->security_token) &&
1833                             !token_contains_name_in_list(
1834                                     uidtoname(p->session_info->utok.uid),
1835                                     p->session_info->info3->base.domain.string,
1836                                     NULL,
1837                                     p->session_info->security_token,
1838                                     lp_printer_admin(snum))) {
1839                                 close_printer_handle(p, r->out.handle);
1840                                 ZERO_STRUCTP(r->out.handle);
1841                                 DEBUG(3,("access DENIED as user is not root, "
1842                                         "has no printoperator privilege, "
1843                                         "not a member of the printoperator builtin group and "
1844                                         "is not in printer admin list"));
1845                                 return WERR_ACCESS_DENIED;
1846                         }
1847
1848                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1849                 }
1850                 else
1851                 {
1852                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1853                 }
1854
1855                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1856                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1857
1858                 /* We fall through to return WERR_OK */
1859                 break;
1860
1861         case SPLHND_PRINTER:
1862                 /* NT doesn't let us connect to a printer if the connecting user
1863                    doesn't have print permission.  */
1864
1865                 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1866                         close_printer_handle(p, r->out.handle);
1867                         ZERO_STRUCTP(r->out.handle);
1868                         return WERR_BADFID;
1869                 }
1870
1871                 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1872                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1873                 }
1874
1875                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1876
1877                 /* map an empty access mask to the minimum access mask */
1878                 if (r->in.access_mask == 0x0)
1879                         r->in.access_mask = PRINTER_ACCESS_USE;
1880
1881                 /*
1882                  * If we are not serving the printer driver for this printer,
1883                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1884                  * will keep NT clients happy  --jerry
1885                  */
1886
1887                 if (lp_use_client_driver(snum)
1888                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1889                 {
1890                         r->in.access_mask = PRINTER_ACCESS_USE;
1891                 }
1892
1893                 /* check smb.conf parameters and the the sec_desc */
1894                 raddr = tsocket_address_inet_addr_string(p->remote_address,
1895                                                          p->mem_ctx);
1896                 if (raddr == NULL) {
1897                         return WERR_NOMEM;
1898                 }
1899
1900                 rc = get_remote_hostname(p->remote_address,
1901                                          &rhost,
1902                                          p->mem_ctx);
1903                 if (rc < 0) {
1904                         return WERR_NOMEM;
1905                 }
1906                 if (strequal(rhost, "UNKNOWN")) {
1907                         rhost = raddr;
1908                 }
1909
1910                 if (!allow_access(lp_hostsdeny(snum), lp_hostsallow(snum),
1911                                   rhost, raddr)) {
1912                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1913                         ZERO_STRUCTP(r->out.handle);
1914                         return WERR_ACCESS_DENIED;
1915                 }
1916
1917                 if (!user_ok_token(uidtoname(p->session_info->utok.uid), NULL,
1918                                    p->session_info->security_token, snum) ||
1919                     !print_access_check(p->session_info,
1920                                         p->msg_ctx,
1921                                         snum,
1922                                         r->in.access_mask)) {
1923                         DEBUG(3, ("access DENIED for printer open\n"));
1924                         close_printer_handle(p, r->out.handle);
1925                         ZERO_STRUCTP(r->out.handle);
1926                         return WERR_ACCESS_DENIED;
1927                 }
1928
1929                 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1930                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1931                         close_printer_handle(p, r->out.handle);
1932                         ZERO_STRUCTP(r->out.handle);
1933                         return WERR_ACCESS_DENIED;
1934                 }
1935
1936                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1937                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1938                 else
1939                         r->in.access_mask = PRINTER_ACCESS_USE;
1940
1941                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1942                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1943
1944                 winreg_create_printer_internal(p->mem_ctx,
1945                                       get_session_info_system(),
1946                                       p->msg_ctx,
1947                                       lp_const_servicename(snum));
1948
1949                 break;
1950
1951         default:
1952                 /* sanity check to prevent programmer error */
1953                 ZERO_STRUCTP(r->out.handle);
1954                 return WERR_BADFID;
1955         }
1956
1957         Printer->access_granted = r->in.access_mask;
1958
1959         /*
1960          * If the client sent a devmode in the OpenPrinter() call, then
1961          * save it here in case we get a job submission on this handle
1962          */
1963
1964          if ((Printer->printer_type != SPLHND_SERVER) &&
1965              r->in.devmode_ctr.devmode) {
1966                 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1967                                 &Printer->devmode);
1968          }
1969
1970 #if 0   /* JERRY -- I'm doubtful this is really effective */
1971         /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1972            optimization in Windows 2000 clients  --jerry */
1973
1974         if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1975                 && (RA_WIN2K == get_remote_arch()) )
1976         {
1977                 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1978                 sys_usleep( 500000 );
1979         }
1980 #endif
1981
1982         return WERR_OK;
1983 }
1984
1985 /****************************************************************
1986  _spoolss_ClosePrinter
1987 ****************************************************************/
1988
1989 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1990                              struct spoolss_ClosePrinter *r)
1991 {
1992         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1993
1994         if (Printer && Printer->document_started) {
1995                 struct spoolss_EndDocPrinter e;
1996
1997                 e.in.handle = r->in.handle;
1998
1999                 _spoolss_EndDocPrinter(p, &e);
2000         }
2001
2002         if (!close_printer_handle(p, r->in.handle))
2003                 return WERR_BADFID;
2004
2005         /* clear the returned printer handle.  Observed behavior
2006            from Win2k server.  Don't think this really matters.
2007            Previous code just copied the value of the closed
2008            handle.    --jerry */
2009
2010         ZERO_STRUCTP(r->out.handle);
2011
2012         return WERR_OK;
2013 }
2014
2015 /****************************************************************
2016  _spoolss_DeletePrinter
2017 ****************************************************************/
2018
2019 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
2020                               struct spoolss_DeletePrinter *r)
2021 {
2022         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2023         WERROR result;
2024         int snum;
2025
2026         if (Printer && Printer->document_started) {
2027                 struct spoolss_EndDocPrinter e;
2028
2029                 e.in.handle = r->in.handle;
2030
2031                 _spoolss_EndDocPrinter(p, &e);
2032         }
2033
2034         if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
2035                 winreg_delete_printer_key_internal(p->mem_ctx,
2036                                           get_session_info_system(),
2037                                           p->msg_ctx,
2038                                           lp_const_servicename(snum),
2039                                           "");
2040         }
2041
2042         result = delete_printer_handle(p, r->in.handle);
2043
2044         return result;
2045 }
2046
2047 /*******************************************************************
2048  * static function to lookup the version id corresponding to an
2049  * long architecture string
2050  ******************************************************************/
2051
2052 static const struct print_architecture_table_node archi_table[]= {
2053
2054         {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
2055         {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
2056         {"Windows NT R4000",     SPL_ARCH_W32MIPS,      2 },
2057         {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,     2 },
2058         {"Windows NT PowerPC",   SPL_ARCH_W32PPC,       2 },
2059         {"Windows IA64",         SPL_ARCH_IA64,         3 },
2060         {"Windows x64",          SPL_ARCH_X64,          3 },
2061         {NULL,                   "",            -1 }
2062 };
2063
2064 static int get_version_id(const char *arch)
2065 {
2066         int i;
2067
2068         for (i=0; archi_table[i].long_archi != NULL; i++)
2069         {
2070                 if (strcmp(arch, archi_table[i].long_archi) == 0)
2071                         return (archi_table[i].version);
2072         }
2073
2074         return -1;
2075 }
2076
2077 /****************************************************************
2078  _spoolss_DeletePrinterDriver
2079 ****************************************************************/
2080
2081 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2082                                     struct spoolss_DeletePrinterDriver *r)
2083 {
2084
2085         struct spoolss_DriverInfo8 *info = NULL;
2086         struct spoolss_DriverInfo8 *info_win2k = NULL;
2087         int                             version;
2088         WERROR                          status;
2089         struct dcerpc_binding_handle *b;
2090
2091         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2092            and not a printer admin, then fail */
2093
2094         if ( (p->session_info->utok.uid != sec_initial_uid())
2095              && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2096                 && !token_contains_name_in_list(
2097                         uidtoname(p->session_info->utok.uid),
2098                         p->session_info->info3->base.domain.string,
2099                         NULL,
2100                         p->session_info->security_token,
2101                         lp_printer_admin(-1)) )
2102         {
2103                 return WERR_ACCESS_DENIED;
2104         }
2105
2106         /* check that we have a valid driver name first */
2107
2108         if ((version = get_version_id(r->in.architecture)) == -1)
2109                 return WERR_INVALID_ENVIRONMENT;
2110
2111         status = winreg_printer_binding_handle(p->mem_ctx,
2112                                                get_session_info_system(),
2113                                                p->msg_ctx,
2114                                                &b);
2115         if (!W_ERROR_IS_OK(status)) {
2116                 return status;
2117         }
2118
2119         status = winreg_get_driver(p->mem_ctx, b,
2120                                    r->in.architecture, r->in.driver,
2121                                    version, &info);
2122         if (!W_ERROR_IS_OK(status)) {
2123                 /* try for Win2k driver if "Windows NT x86" */
2124
2125                 if ( version == 2 ) {
2126                         version = 3;
2127
2128                         status = winreg_get_driver(p->mem_ctx, b,
2129                                                    r->in.architecture,
2130                                                    r->in.driver,
2131                                                    version, &info);
2132                         if (!W_ERROR_IS_OK(status)) {
2133                                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2134                                 goto done;
2135                         }
2136                 }
2137                 /* otherwise it was a failure */
2138                 else {
2139                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2140                         goto done;
2141                 }
2142
2143         }
2144
2145         if (printer_driver_in_use(p->mem_ctx,
2146                                   get_session_info_system(),
2147                                   p->msg_ctx,
2148                                   info)) {
2149                 status = WERR_PRINTER_DRIVER_IN_USE;
2150                 goto done;
2151         }
2152
2153         if (version == 2) {
2154                 status = winreg_get_driver(p->mem_ctx, b,
2155                                            r->in.architecture,
2156                                            r->in.driver, 3, &info_win2k);
2157                 if (W_ERROR_IS_OK(status)) {
2158                         /* if we get to here, we now have 2 driver info structures to remove */
2159                         /* remove the Win2k driver first*/
2160
2161                         status = winreg_del_driver(p->mem_ctx, b,
2162                                                    info_win2k, 3);
2163                         talloc_free(info_win2k);
2164
2165                         /* this should not have failed---if it did, report to client */
2166                         if (!W_ERROR_IS_OK(status)) {
2167                                 goto done;
2168                         }
2169                 }
2170         }
2171
2172         status = winreg_del_driver(p->mem_ctx, b,
2173                                    info, version);
2174
2175 done:
2176         talloc_free(info);
2177
2178         return status;
2179 }
2180
2181 /****************************************************************
2182  _spoolss_DeletePrinterDriverEx
2183 ****************************************************************/
2184
2185 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2186                                       struct spoolss_DeletePrinterDriverEx *r)
2187 {
2188         struct spoolss_DriverInfo8      *info = NULL;
2189         struct spoolss_DriverInfo8      *info_win2k = NULL;
2190         int                             version;
2191         bool                            delete_files;
2192         WERROR                          status;
2193         struct dcerpc_binding_handle *b;
2194
2195         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2196            and not a printer admin, then fail */
2197
2198         if ( (p->session_info->utok.uid != sec_initial_uid())
2199                 && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2200                 && !token_contains_name_in_list(
2201                         uidtoname(p->session_info->utok.uid),
2202                         p->session_info->info3->base.domain.string,
2203                         NULL,
2204                         p->session_info->security_token, lp_printer_admin(-1)) )
2205         {
2206                 return WERR_ACCESS_DENIED;
2207         }
2208
2209         /* check that we have a valid driver name first */
2210         if ((version = get_version_id(r->in.architecture)) == -1) {
2211                 /* this is what NT returns */
2212                 return WERR_INVALID_ENVIRONMENT;
2213         }
2214
2215         if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2216                 version = r->in.version;
2217
2218         status = winreg_printer_binding_handle(p->mem_ctx,
2219                                                get_session_info_system(),
2220                                                p->msg_ctx,
2221                                                &b);
2222         if (!W_ERROR_IS_OK(status)) {
2223                 return status;
2224         }
2225
2226         status = winreg_get_driver(p->mem_ctx, b,
2227                                    r->in.architecture,
2228                                    r->in.driver,
2229                                    version,
2230                                    &info);
2231         if (!W_ERROR_IS_OK(status)) {
2232                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2233
2234                 /*
2235                  * if the client asked for a specific version,
2236                  * or this is something other than Windows NT x86,
2237                  * then we've failed
2238                  */
2239
2240                 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2241                         goto done;
2242
2243                 /* try for Win2k driver if "Windows NT x86" */
2244
2245                 version = 3;
2246                 status = winreg_get_driver(info, b,
2247                                            r->in.architecture,
2248                                            r->in.driver,
2249                                            version, &info);
2250                 if (!W_ERROR_IS_OK(status)) {
2251                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2252                         goto done;
2253                 }
2254         }
2255
2256         if (printer_driver_in_use(info,
2257                                   get_session_info_system(),
2258                                   p->msg_ctx,
2259                                   info)) {
2260                 status = WERR_PRINTER_DRIVER_IN_USE;
2261                 goto done;
2262         }
2263
2264         /*
2265          * we have a couple of cases to consider.
2266          * (1) Are any files in use?  If so and DPD_DELTE_ALL_FILE is set,
2267          *     then the delete should fail if **any** files overlap with
2268          *     other drivers
2269          * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2270          *     non-overlapping files
2271          * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2272          *     is set, the do not delete any files
2273          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2274          */
2275
2276         delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2277
2278         /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2279
2280         if (delete_files &&
2281             (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2282             printer_driver_files_in_use(info,
2283                                         get_session_info_system(),
2284                                         p->msg_ctx,
2285                                         info)) {
2286                 /* no idea of the correct error here */
2287                 status = WERR_ACCESS_DENIED;
2288                 goto done;
2289         }
2290
2291
2292         /* also check for W32X86/3 if necessary; maybe we already have? */
2293
2294         if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION)  ) {
2295                 status = winreg_get_driver(info, b,
2296                                            r->in.architecture,
2297                                            r->in.driver, 3, &info_win2k);
2298                 if (W_ERROR_IS_OK(status)) {
2299
2300                         if (delete_files &&
2301                             (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2302                             printer_driver_files_in_use(info,
2303                                                         get_session_info_system(),
2304                                                         p->msg_ctx,
2305                                                         info_win2k)) {
2306                                 /* no idea of the correct error here */
2307                                 talloc_free(info_win2k);
2308                                 status = WERR_ACCESS_DENIED;
2309                                 goto done;
2310                         }
2311
2312                         /* if we get to here, we now have 2 driver info structures to remove */
2313                         /* remove the Win2k driver first*/
2314
2315                         status = winreg_del_driver(info, b,
2316                                                    info_win2k,
2317                                                    3);
2318
2319                         /* this should not have failed---if it did, report to client */
2320
2321                         if (!W_ERROR_IS_OK(status)) {
2322                                 goto done;
2323                         }
2324
2325                         /*
2326                          * now delete any associated files if delete_files is
2327                          * true. Even if this part failes, we return succes
2328                          * because the driver doesn not exist any more
2329                          */
2330                         if (delete_files) {
2331                                 delete_driver_files(get_session_info_system(),
2332                                                     info_win2k);
2333                         }
2334                 }
2335         }
2336
2337         status = winreg_del_driver(info, b,
2338                                    info,
2339                                    version);
2340         if (!W_ERROR_IS_OK(status)) {
2341                 goto done;
2342         }
2343
2344         /*
2345          * now delete any associated files if delete_files is
2346          * true. Even if this part failes, we return succes
2347          * because the driver doesn not exist any more
2348          */
2349         if (delete_files) {
2350                 delete_driver_files(get_session_info_system(), info);
2351         }
2352
2353 done:
2354         talloc_free(info);
2355         return status;
2356 }
2357
2358
2359 /********************************************************************
2360  GetPrinterData on a printer server Handle.
2361 ********************************************************************/
2362
2363 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2364                                             const char *value,
2365                                             enum winreg_Type *type,
2366                                             union spoolss_PrinterData *data)
2367 {
2368         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2369
2370         if (!strcasecmp_m(value, "W3SvcInstalled")) {
2371                 *type = REG_DWORD;
2372                 data->value = 0x00;
2373                 return WERR_OK;
2374         }
2375
2376         if (!strcasecmp_m(value, "BeepEnabled")) {
2377                 *type = REG_DWORD;
2378                 data->value = 0x00;
2379                 return WERR_OK;
2380         }
2381
2382         if (!strcasecmp_m(value, "EventLog")) {
2383                 *type = REG_DWORD;
2384                 /* formally was 0x1b */
2385                 data->value = 0x00;
2386                 return WERR_OK;
2387         }
2388
2389         if (!strcasecmp_m(value, "NetPopup")) {
2390                 *type = REG_DWORD;
2391                 data->value = 0x00;
2392                 return WERR_OK;
2393         }
2394
2395         if (!strcasecmp_m(value, "MajorVersion")) {
2396                 *type = REG_DWORD;
2397
2398                 /* Windows NT 4.0 seems to not allow uploading of drivers
2399                    to a server that reports 0x3 as the MajorVersion.
2400                    need to investigate more how Win2k gets around this .
2401                    -- jerry */
2402
2403                 if (RA_WINNT == get_remote_arch()) {
2404                         data->value = 0x02;
2405                 } else {
2406                         data->value = 0x03;
2407                 }
2408
2409                 return WERR_OK;
2410         }
2411
2412         if (!strcasecmp_m(value, "MinorVersion")) {
2413                 *type = REG_DWORD;
2414                 data->value = 0x00;
2415                 return WERR_OK;
2416         }
2417
2418         /* REG_BINARY
2419          *  uint32_t size        = 0x114
2420          *  uint32_t major       = 5
2421          *  uint32_t minor       = [0|1]
2422          *  uint32_t build       = [2195|2600]
2423          *  extra unicode string = e.g. "Service Pack 3"
2424          */
2425         if (!strcasecmp_m(value, "OSVersion")) {
2426                 DATA_BLOB blob;
2427                 enum ndr_err_code ndr_err;
2428                 struct spoolss_OSVersion os;
2429
2430                 os.major                = 5;    /* Windows 2000 == 5.0 */
2431                 os.minor                = 0;
2432                 os.build                = 2195; /* build */
2433                 os.extra_string         = "";   /* leave extra string empty */
2434
2435                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2436                         (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2437                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2438                         return WERR_GENERAL_FAILURE;
2439                 }
2440
2441                 *type = REG_BINARY;
2442                 data->binary = blob;
2443
2444                 return WERR_OK;
2445         }
2446
2447
2448         if (!strcasecmp_m(value, "DefaultSpoolDirectory")) {
2449                 *type = REG_SZ;
2450
2451                 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2452                 W_ERROR_HAVE_NO_MEMORY(data->string);
2453
2454                 return WERR_OK;
2455         }
2456
2457         if (!strcasecmp_m(value, "Architecture")) {
2458                 *type = REG_SZ;
2459                 data->string = talloc_strdup(mem_ctx,
2460                         lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2461                 W_ERROR_HAVE_NO_MEMORY(data->string);
2462
2463                 return WERR_OK;
2464         }
2465
2466         if (!strcasecmp_m(value, "DsPresent")) {
2467                 *type = REG_DWORD;
2468
2469                 /* only show the publish check box if we are a
2470                    member of a AD domain */
2471
2472                 if (lp_security() == SEC_ADS) {
2473                         data->value = 0x01;
2474                 } else {
2475                         data->value = 0x00;
2476                 }
2477                 return WERR_OK;
2478         }
2479
2480         if (!strcasecmp_m(value, "DNSMachineName")) {
2481                 const char *hostname = get_mydnsfullname();
2482
2483                 if (!hostname) {
2484                         return WERR_BADFILE;
2485                 }
2486
2487                 *type = REG_SZ;
2488                 data->string = talloc_strdup(mem_ctx, hostname);
2489                 W_ERROR_HAVE_NO_MEMORY(data->string);
2490
2491                 return WERR_OK;
2492         }
2493
2494         *type = REG_NONE;
2495
2496         return WERR_INVALID_PARAM;
2497 }
2498
2499 /****************************************************************
2500  _spoolss_GetPrinterData
2501 ****************************************************************/
2502
2503 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2504                                struct spoolss_GetPrinterData *r)
2505 {
2506         struct spoolss_GetPrinterDataEx r2;
2507
2508         r2.in.handle            = r->in.handle;
2509         r2.in.key_name          = "PrinterDriverData";
2510         r2.in.value_name        = r->in.value_name;
2511         r2.in.offered           = r->in.offered;
2512         r2.out.type             = r->out.type;
2513         r2.out.data             = r->out.data;
2514         r2.out.needed           = r->out.needed;
2515
2516         return _spoolss_GetPrinterDataEx(p, &r2);
2517 }
2518
2519 /*********************************************************
2520  Connect to the client machine.
2521 **********************************************************/
2522
2523 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2524                         struct sockaddr_storage *client_ss, const char *remote_machine)
2525 {
2526         NTSTATUS ret;
2527         struct cli_state *the_cli;
2528         struct sockaddr_storage rm_addr;
2529         char addr[INET6_ADDRSTRLEN];
2530
2531         if ( is_zero_addr(client_ss) ) {
2532                 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2533                         remote_machine));
2534                 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2535                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2536                         return false;
2537                 }
2538                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2539         } else {
2540                 rm_addr = *client_ss;
2541                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2542                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2543                         addr));
2544         }
2545
2546         if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2547                 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2548                         addr));
2549                 return false;
2550         }
2551
2552         /* setup the connection */
2553         ret = cli_full_connection( &the_cli, lp_netbios_name(), remote_machine,
2554                 &rm_addr, 0, "IPC$", "IPC",
2555                 "", /* username */
2556                 "", /* domain */
2557                 "", /* password */
2558                 0, lp_client_signing());
2559
2560         if ( !NT_STATUS_IS_OK( ret ) ) {
2561                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2562                         remote_machine ));
2563                 return false;
2564         }
2565
2566         if ( the_cli->protocol != PROTOCOL_NT1 ) {
2567                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2568                 cli_shutdown(the_cli);
2569                 return false;
2570         }
2571
2572         /*
2573          * Ok - we have an anonymous connection to the IPC$ share.
2574          * Now start the NT Domain stuff :-).
2575          */
2576
2577         ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2578         if (!NT_STATUS_IS_OK(ret)) {
2579                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2580                         remote_machine, nt_errstr(ret)));
2581                 cli_shutdown(the_cli);
2582                 return false;
2583         }
2584
2585         return true;
2586 }
2587
2588 /***************************************************************************
2589  Connect to the client.
2590 ****************************************************************************/
2591
2592 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2593                                         uint32_t localprinter,
2594                                         enum winreg_Type type,
2595                                         struct policy_handle *handle,
2596                                         struct notify_back_channel **_chan,
2597                                         struct sockaddr_storage *client_ss,
2598                                         struct messaging_context *msg_ctx)
2599 {
2600         WERROR result;
2601         NTSTATUS status;
2602         struct notify_back_channel *chan;
2603
2604         for (chan = back_channels; chan; chan = chan->next) {
2605                 if (memcmp(&chan->client_address, client_ss,
2606                            sizeof(struct sockaddr_storage)) == 0) {
2607                         break;
2608                 }
2609         }
2610
2611         /*
2612          * If it's the first connection, contact the client
2613          * and connect to the IPC$ share anonymously
2614          */
2615         if (!chan) {
2616                 fstring unix_printer;
2617
2618                 /* the +2 is to strip the leading 2 backslashs */
2619                 fstrcpy(unix_printer, printer + 2);
2620
2621                 chan = talloc_zero(back_channels, struct notify_back_channel);
2622                 if (!chan) {
2623                         return false;
2624                 }
2625                 chan->client_address = *client_ss;
2626
2627                 if (!spoolss_connect_to_client(&chan->cli_pipe, client_ss, unix_printer)) {
2628                         TALLOC_FREE(chan);
2629                         return false;
2630                 }
2631                 chan->binding_handle = chan->cli_pipe->binding_handle;
2632
2633                 DLIST_ADD(back_channels, chan);
2634
2635                 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2636                                    receive_notify2_message_list);
2637                 /* Tell the connections db we're now interested in printer
2638                  * notify messages. */
2639                 serverid_register_msg_flags(messaging_server_id(msg_ctx),
2640                                             true, FLAG_MSG_PRINT_NOTIFY);
2641         }
2642
2643         /*
2644          * Tell the specific printing tdb we want messages for this printer
2645          * by registering our PID.
2646          */
2647
2648         if (!print_notify_register_pid(snum)) {
2649                 DEBUG(0, ("Failed to register our pid for printer %s\n",
2650                           printer));
2651         }
2652
2653         status = dcerpc_spoolss_ReplyOpenPrinter(chan->binding_handle,
2654                                                  talloc_tos(),
2655                                                  printer,
2656                                                  localprinter,
2657                                                  type,
2658                                                  0,
2659                                                  NULL,
2660                                                  handle,
2661                                                  &result);
2662         if (!NT_STATUS_IS_OK(status)) {
2663                 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2664                 result = ntstatus_to_werror(status);
2665         } else if (!W_ERROR_IS_OK(result)) {
2666                 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2667         }
2668
2669         chan->active_connections++;
2670         *_chan = chan;
2671
2672         return (W_ERROR_IS_OK(result));
2673 }
2674
2675 /****************************************************************
2676  ****************************************************************/
2677
2678 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2679                                                              const struct spoolss_NotifyOption *r)
2680 {
2681         struct spoolss_NotifyOption *option;
2682         uint32_t i,k;
2683
2684         if (!r) {
2685                 return NULL;
2686         }
2687
2688         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2689         if (!option) {
2690                 return NULL;
2691         }
2692
2693         *option = *r;
2694
2695         if (!option->count) {
2696                 return option;
2697         }
2698
2699         option->types = talloc_zero_array(option,
2700                 struct spoolss_NotifyOptionType, option->count);
2701         if (!option->types) {
2702                 talloc_free(option);
2703                 return NULL;
2704         }
2705
2706         for (i=0; i < option->count; i++) {
2707                 option->types[i] = r->types[i];
2708
2709                 if (option->types[i].count) {
2710                         option->types[i].fields = talloc_zero_array(option,
2711                                 union spoolss_Field, option->types[i].count);
2712                         if (!option->types[i].fields) {
2713                                 talloc_free(option);
2714                                 return NULL;
2715                         }
2716                         for (k=0; k<option->types[i].count; k++) {
2717                                 option->types[i].fields[k] =
2718                                         r->types[i].fields[k];
2719                         }
2720                 }
2721         }
2722
2723         return option;
2724 }
2725
2726 /****************************************************************
2727  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2728  *
2729  * before replying OK: status=0 a rpc call is made to the workstation
2730  * asking ReplyOpenPrinter
2731  *
2732  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2733  * called from api_spoolss_rffpcnex
2734 ****************************************************************/
2735
2736 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2737                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2738 {
2739         int snum = -1;
2740         struct spoolss_NotifyOption *option = r->in.notify_options;
2741         struct sockaddr_storage client_ss;
2742         socklen_t client_len;
2743
2744         /* store the notify value in the printer struct */
2745
2746         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2747
2748         if (!Printer) {
2749                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2750                         "Invalid handle (%s:%u:%u).\n",
2751                         OUR_HANDLE(r->in.handle)));
2752                 return WERR_BADFID;
2753         }
2754
2755         Printer->notify.flags           = r->in.flags;
2756         Printer->notify.options         = r->in.options;
2757         Printer->notify.printerlocal    = r->in.printer_local;
2758         Printer->notify.msg_ctx         = p->msg_ctx;
2759
2760         TALLOC_FREE(Printer->notify.option);
2761         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2762
2763         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2764
2765         /* Connect to the client machine and send a ReplyOpenPrinter */
2766
2767         if ( Printer->printer_type == SPLHND_SERVER)
2768                 snum = -1;
2769         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2770                         !get_printer_snum(p, r->in.handle, &snum, NULL) )
2771                 return WERR_BADFID;
2772
2773         DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2774                   "remote_address is %s\n",
2775                   tsocket_address_string(p->remote_address, p->mem_ctx)));
2776
2777         if (!lp_print_notify_backchannel(snum)) {
2778                 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2779                         "backchannel disabled\n"));
2780                 return WERR_SERVER_UNAVAILABLE;
2781         }
2782
2783         client_len = tsocket_address_bsd_sockaddr(p->remote_address,
2784                                                   (struct sockaddr *) &client_ss,
2785                                                   sizeof(struct sockaddr_storage));
2786         if (client_len < 0) {
2787                 return WERR_NOMEM;
2788         }
2789
2790         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2791                                         Printer->notify.printerlocal, REG_SZ,
2792                                         &Printer->notify.cli_hnd,
2793                                         &Printer->notify.cli_chan,
2794                                         &client_ss, p->msg_ctx)) {
2795                 return WERR_SERVER_UNAVAILABLE;
2796         }
2797
2798         return WERR_OK;
2799 }
2800
2801 /*******************************************************************
2802  * fill a notify_info_data with the servername
2803  ********************************************************************/
2804
2805 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2806                                        int snum,
2807                                        struct spoolss_Notify *data,
2808                                        print_queue_struct *queue,
2809                                        struct spoolss_PrinterInfo2 *pinfo2,
2810                                        TALLOC_CTX *mem_ctx)
2811 {
2812         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2813 }
2814
2815 /*******************************************************************
2816  * fill a notify_info_data with the printername (not including the servername).
2817  ********************************************************************/
2818
2819 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2820                                         int snum,
2821                                         struct spoolss_Notify *data,
2822                                         print_queue_struct *queue,
2823                                         struct spoolss_PrinterInfo2 *pinfo2,
2824                                         TALLOC_CTX *mem_ctx)
2825 {
2826         /* the notify name should not contain the \\server\ part */
2827         const char *p = strrchr(pinfo2->printername, '\\');
2828
2829         if (!p) {
2830                 p = pinfo2->printername;
2831         } else {
2832                 p++;
2833         }
2834
2835         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2836 }
2837
2838 /*******************************************************************
2839  * fill a notify_info_data with the servicename
2840  ********************************************************************/
2841
2842 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2843                                       int snum,
2844                                       struct spoolss_Notify *data,
2845                                       print_queue_struct *queue,
2846                                       struct spoolss_PrinterInfo2 *pinfo2,
2847                                       TALLOC_CTX *mem_ctx)
2848 {
2849         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2850 }
2851
2852 /*******************************************************************
2853  * fill a notify_info_data with the port name
2854  ********************************************************************/
2855
2856 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2857                                      int snum,
2858                                      struct spoolss_Notify *data,
2859                                      print_queue_struct *queue,
2860                                      struct spoolss_PrinterInfo2 *pinfo2,
2861                                      TALLOC_CTX *mem_ctx)
2862 {
2863         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2864 }
2865
2866 /*******************************************************************
2867  * fill a notify_info_data with the printername
2868  * but it doesn't exist, have to see what to do
2869  ********************************************************************/
2870
2871 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2872                                        int snum,
2873                                        struct spoolss_Notify *data,
2874                                        print_queue_struct *queue,
2875                                        struct spoolss_PrinterInfo2 *pinfo2,
2876                                        TALLOC_CTX *mem_ctx)
2877 {
2878         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2879 }
2880
2881 /*******************************************************************
2882  * fill a notify_info_data with the comment
2883  ********************************************************************/
2884
2885 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2886                                    int snum,
2887                                    struct spoolss_Notify *data,
2888                                    print_queue_struct *queue,
2889                                    struct spoolss_PrinterInfo2 *pinfo2,
2890                                    TALLOC_CTX *mem_ctx)
2891 {
2892         const char *p;
2893
2894         if (*pinfo2->comment == '\0') {
2895                 p = lp_comment(snum);
2896         } else {
2897                 p = pinfo2->comment;
2898         }
2899
2900         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2901 }
2902
2903 /*******************************************************************
2904  * fill a notify_info_data with the comment
2905  * location = "Room 1, floor 2, building 3"
2906  ********************************************************************/
2907
2908 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2909                                     int snum,
2910                                     struct spoolss_Notify *data,
2911                                     print_queue_struct *queue,
2912                                     struct spoolss_PrinterInfo2 *pinfo2,
2913                                     TALLOC_CTX *mem_ctx)
2914 {
2915         const char *loc = pinfo2->location;
2916         NTSTATUS status;
2917
2918         status = printer_list_get_printer(mem_ctx,
2919                                           pinfo2->sharename,
2920                                           NULL,
2921                                           &loc,
2922                                           NULL);
2923         if (NT_STATUS_IS_OK(status)) {
2924                 if (loc == NULL) {
2925                         loc = pinfo2->location;
2926                 }
2927         }
2928
2929         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, loc);
2930 }
2931
2932 /*******************************************************************
2933  * fill a notify_info_data with the device mode
2934  * jfm:xxxx don't to it for know but that's a real problem !!!
2935  ********************************************************************/
2936
2937 static void spoolss_notify_devmode(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         /* for a dummy implementation we have to zero the fields */
2945         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2946 }
2947
2948 /*******************************************************************
2949  * fill a notify_info_data with the separator file name
2950  ********************************************************************/
2951
2952 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2953                                    int snum,
2954                                    struct spoolss_Notify *data,
2955                                    print_queue_struct *queue,
2956                                    struct spoolss_PrinterInfo2 *pinfo2,
2957                                    TALLOC_CTX *mem_ctx)
2958 {
2959         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2960 }
2961
2962 /*******************************************************************
2963  * fill a notify_info_data with the print processor
2964  * jfm:xxxx return always winprint to indicate we don't do anything to it
2965  ********************************************************************/
2966
2967 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2968                                            int snum,
2969                                            struct spoolss_Notify *data,
2970                                            print_queue_struct *queue,
2971                                            struct spoolss_PrinterInfo2 *pinfo2,
2972                                            TALLOC_CTX *mem_ctx)
2973 {
2974         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2975 }
2976
2977 /*******************************************************************
2978  * fill a notify_info_data with the print processor options
2979  * jfm:xxxx send an empty string
2980  ********************************************************************/
2981
2982 static void spoolss_notify_parameters(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_STRING(data, pinfo2->parameters);
2990 }
2991
2992 /*******************************************************************
2993  * fill a notify_info_data with the data type
2994  * jfm:xxxx always send RAW as data type
2995  ********************************************************************/
2996
2997 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2998                                     int snum,
2999                                     struct spoolss_Notify *data,
3000                                     print_queue_struct *queue,
3001                                     struct spoolss_PrinterInfo2 *pinfo2,
3002                                     TALLOC_CTX *mem_ctx)
3003 {
3004         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
3005 }
3006
3007 /*******************************************************************
3008  * fill a notify_info_data with the security descriptor
3009  * jfm:xxxx send an null pointer to say no security desc
3010  * have to implement security before !
3011  ********************************************************************/
3012
3013 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
3014                                          int snum,
3015                                          struct spoolss_Notify *data,
3016                                          print_queue_struct *queue,
3017                                          struct spoolss_PrinterInfo2 *pinfo2,
3018                                          TALLOC_CTX *mem_ctx)
3019 {
3020         SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
3021 }
3022
3023 /*******************************************************************
3024  * fill a notify_info_data with the attributes
3025  * jfm:xxxx a samba printer is always shared
3026  ********************************************************************/
3027
3028 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
3029                                       int snum,
3030                                       struct spoolss_Notify *data,
3031                                       print_queue_struct *queue,
3032                                       struct spoolss_PrinterInfo2 *pinfo2,
3033                                       TALLOC_CTX *mem_ctx)
3034 {
3035         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
3036 }
3037
3038 /*******************************************************************
3039  * fill a notify_info_data with the priority
3040  ********************************************************************/
3041
3042 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
3043                                     int snum,
3044                                     struct spoolss_Notify *data,
3045                                     print_queue_struct *queue,
3046                                     struct spoolss_PrinterInfo2 *pinfo2,
3047                                     TALLOC_CTX *mem_ctx)
3048 {
3049         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
3050 }
3051
3052 /*******************************************************************
3053  * fill a notify_info_data with the default priority
3054  ********************************************************************/
3055
3056 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
3057                                             int snum,
3058                                             struct spoolss_Notify *data,
3059                                             print_queue_struct *queue,
3060                                             struct spoolss_PrinterInfo2 *pinfo2,
3061                                             TALLOC_CTX *mem_ctx)
3062 {
3063         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
3064 }
3065
3066 /*******************************************************************
3067  * fill a notify_info_data with the start time
3068  ********************************************************************/
3069
3070 static void spoolss_notify_start_time(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         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3078 }
3079
3080 /*******************************************************************
3081  * fill a notify_info_data with the until time
3082  ********************************************************************/
3083
3084 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3085                                       int snum,
3086                                       struct spoolss_Notify *data,
3087                                       print_queue_struct *queue,
3088                                       struct spoolss_PrinterInfo2 *pinfo2,
3089                                       TALLOC_CTX *mem_ctx)
3090 {
3091         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3092 }
3093
3094 /*******************************************************************
3095  * fill a notify_info_data with the status
3096  ********************************************************************/
3097
3098 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3099                                   int snum,
3100                                   struct spoolss_Notify *data,
3101                                   print_queue_struct *queue,
3102                                   struct spoolss_PrinterInfo2 *pinfo2,
3103                                   TALLOC_CTX *mem_ctx)
3104 {
3105         print_status_struct status;
3106
3107         print_queue_length(msg_ctx, snum, &status);
3108         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3109 }
3110
3111 /*******************************************************************
3112  * fill a notify_info_data with the number of jobs queued
3113  ********************************************************************/
3114
3115 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3116                                  int snum,
3117                                  struct spoolss_Notify *data,
3118                                  print_queue_struct *queue,
3119                                  struct spoolss_PrinterInfo2 *pinfo2,
3120                                  TALLOC_CTX *mem_ctx)
3121 {
3122         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3123                 data, print_queue_length(msg_ctx, snum, NULL));
3124 }
3125
3126 /*******************************************************************
3127  * fill a notify_info_data with the average ppm
3128  ********************************************************************/
3129
3130 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3131                                        int snum,
3132                                        struct spoolss_Notify *data,
3133                                        print_queue_struct *queue,
3134                                        struct spoolss_PrinterInfo2 *pinfo2,
3135                                        TALLOC_CTX *mem_ctx)
3136 {
3137         /* always respond 8 pages per minutes */
3138         /* a little hard ! */
3139         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3140 }
3141
3142 /*******************************************************************
3143  * fill a notify_info_data with username
3144  ********************************************************************/
3145
3146 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3147                                     int snum,
3148                                     struct spoolss_Notify *data,
3149                                     print_queue_struct *queue,
3150                                     struct spoolss_PrinterInfo2 *pinfo2,
3151                                     TALLOC_CTX *mem_ctx)
3152 {
3153         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3154 }
3155
3156 /*******************************************************************
3157  * fill a notify_info_data with job status
3158  ********************************************************************/
3159
3160 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3161                                       int snum,
3162                                       struct spoolss_Notify *data,
3163                                       print_queue_struct *queue,
3164                                       struct spoolss_PrinterInfo2 *pinfo2,
3165                                       TALLOC_CTX *mem_ctx)
3166 {
3167         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3168 }
3169
3170 /*******************************************************************
3171  * fill a notify_info_data with job name
3172  ********************************************************************/
3173
3174 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3175                                     int snum,
3176                                     struct spoolss_Notify *data,
3177                                     print_queue_struct *queue,
3178                                     struct spoolss_PrinterInfo2 *pinfo2,
3179                                     TALLOC_CTX *mem_ctx)
3180 {
3181         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3182 }
3183
3184 /*******************************************************************
3185  * fill a notify_info_data with job status
3186  ********************************************************************/
3187
3188 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3189                                              int snum,
3190                                              struct spoolss_Notify *data,
3191                                              print_queue_struct *queue,
3192                                              struct spoolss_PrinterInfo2 *pinfo2,
3193                                              TALLOC_CTX *mem_ctx)
3194 {
3195         /*
3196          * Now we're returning job status codes we just return a "" here. JRA.
3197          */
3198
3199         const char *p = "";
3200
3201 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3202         p = "unknown";
3203
3204         switch (queue->status) {
3205         case LPQ_QUEUED:
3206                 p = "Queued";
3207                 break;
3208         case LPQ_PAUSED:
3209                 p = "";    /* NT provides the paused string */
3210                 break;
3211         case LPQ_SPOOLING:
3212                 p = "Spooling";
3213                 break;
3214         case LPQ_PRINTING:
3215                 p = "Printing";
3216                 break;
3217         }
3218 #endif /* NO LONGER NEEDED. */
3219
3220         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3221 }
3222
3223 /*******************************************************************
3224  * fill a notify_info_data with job time
3225  ********************************************************************/
3226
3227 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3228                                     int snum,
3229                                     struct spoolss_Notify *data,
3230                                     print_queue_struct *queue,
3231                                     struct spoolss_PrinterInfo2 *pinfo2,
3232                                     TALLOC_CTX *mem_ctx)
3233 {
3234         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3235 }
3236
3237 /*******************************************************************
3238  * fill a notify_info_data with job size
3239  ********************************************************************/
3240
3241 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3242                                     int snum,
3243                                     struct spoolss_Notify *data,
3244                                     print_queue_struct *queue,
3245                                     struct spoolss_PrinterInfo2 *pinfo2,
3246                                     TALLOC_CTX *mem_ctx)
3247 {
3248         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3249 }
3250
3251 /*******************************************************************
3252  * fill a notify_info_data with page info
3253  ********************************************************************/
3254 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3255                                        int snum,
3256                                 struct spoolss_Notify *data,
3257                                 print_queue_struct *queue,
3258                                 struct spoolss_PrinterInfo2 *pinfo2,
3259                                 TALLOC_CTX *mem_ctx)
3260 {
3261         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3262 }
3263
3264 /*******************************************************************
3265  * fill a notify_info_data with pages printed info.
3266  ********************************************************************/
3267 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3268                                          int snum,
3269                                 struct spoolss_Notify *data,
3270                                 print_queue_struct *queue,
3271                                 struct spoolss_PrinterInfo2 *pinfo2,
3272                                 TALLOC_CTX *mem_ctx)
3273 {
3274         /* Add code when back-end tracks this */
3275         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3276 }
3277
3278 /*******************************************************************
3279  Fill a notify_info_data with job position.
3280  ********************************************************************/
3281
3282 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3283                                         int snum,
3284                                         struct spoolss_Notify *data,
3285                                         print_queue_struct *queue,
3286                                         struct spoolss_PrinterInfo2 *pinfo2,
3287                                         TALLOC_CTX *mem_ctx)
3288 {
3289         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3290 }
3291
3292 /*******************************************************************
3293  Fill a notify_info_data with submitted time.
3294  ********************************************************************/
3295
3296 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3297                                           int snum,
3298                                           struct spoolss_Notify *data,
3299                                           print_queue_struct *queue,
3300                                           struct spoolss_PrinterInfo2 *pinfo2,
3301                                           TALLOC_CTX *mem_ctx)
3302 {
3303         data->data.string.string = NULL;
3304         data->data.string.size = 0;
3305
3306         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3307                                &data->data.string.string,
3308                                &data->data.string.size);
3309
3310 }
3311
3312 struct s_notify_info_data_table
3313 {
3314         enum spoolss_NotifyType type;
3315         uint16_t field;
3316         const char *name;
3317         enum spoolss_NotifyTable variable_type;
3318         void (*fn) (struct messaging_context *msg_ctx,
3319                     int snum, struct spoolss_Notify *data,
3320                     print_queue_struct *queue,
3321                     struct spoolss_PrinterInfo2 *pinfo2,
3322                     TALLOC_CTX *mem_ctx);
3323 };
3324
3325 /* A table describing the various print notification constants and
3326    whether the notification data is a pointer to a variable sized
3327    buffer, a one value uint32_t or a two value uint32_t. */
3328
3329 static const struct s_notify_info_data_table notify_info_data_table[] =
3330 {
3331 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME,         "PRINTER_NOTIFY_FIELD_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3332 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME,        "PRINTER_NOTIFY_FIELD_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3333 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME,          "PRINTER_NOTIFY_FIELD_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
3334 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME,           "PRINTER_NOTIFY_FIELD_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3335 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME,         "PRINTER_NOTIFY_FIELD_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3336 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT,             "PRINTER_NOTIFY_FIELD_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
3337 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION,            "PRINTER_NOTIFY_FIELD_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
3338 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE,             "PRINTER_NOTIFY_FIELD_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3339 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE,             "PRINTER_NOTIFY_FIELD_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
3340 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR,     "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3341 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS,          "PRINTER_NOTIFY_FIELD_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3342 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE,            "PRINTER_NOTIFY_FIELD_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3343 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
3344 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES,          "PRINTER_NOTIFY_FIELD_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
3345 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY,            "PRINTER_NOTIFY_FIELD_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3346 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
3347 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME,          "PRINTER_NOTIFY_FIELD_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3348 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME,          "PRINTER_NOTIFY_FIELD_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3349 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS,              "PRINTER_NOTIFY_FIELD_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
3350 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING,       "PRINTER_NOTIFY_FIELD_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
3351 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS,               "PRINTER_NOTIFY_FIELD_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
3352 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM,         "PRINTER_NOTIFY_FIELD_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
3353 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES,         "PRINTER_NOTIFY_FIELD_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
3354 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED,       "PRINTER_NOTIFY_FIELD_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3355 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES,         "PRINTER_NOTIFY_FIELD_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
3356 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED,       "PRINTER_NOTIFY_FIELD_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3357 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINTER_NAME,            "JOB_NOTIFY_FIELD_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3358 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_MACHINE_NAME,            "JOB_NOTIFY_FIELD_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3359 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PORT_NAME,               "JOB_NOTIFY_FIELD_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3360 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_USER_NAME,               "JOB_NOTIFY_FIELD_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
3361 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_NOTIFY_NAME,             "JOB_NOTIFY_FIELD_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
3362 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DATATYPE,                "JOB_NOTIFY_FIELD_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3363 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINT_PROCESSOR,         "JOB_NOTIFY_FIELD_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3364 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PARAMETERS,              "JOB_NOTIFY_FIELD_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3365 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DRIVER_NAME,             "JOB_NOTIFY_FIELD_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3366 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DEVMODE,                 "JOB_NOTIFY_FIELD_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3367 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS,                  "JOB_NOTIFY_FIELD_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
3368 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS_STRING,           "JOB_NOTIFY_FIELD_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
3369 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
3370 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DOCUMENT,                "JOB_NOTIFY_FIELD_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
3371 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRIORITY,                "JOB_NOTIFY_FIELD_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3372 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_POSITION,                "JOB_NOTIFY_FIELD_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
3373 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SUBMITTED,               "JOB_NOTIFY_FIELD_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
3374 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_START_TIME,              "JOB_NOTIFY_FIELD_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3375 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_UNTIL_TIME,              "JOB_NOTIFY_FIELD_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3376 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TIME,                    "JOB_NOTIFY_FIELD_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
3377 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_PAGES,             "JOB_NOTIFY_FIELD_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
3378 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PAGES_PRINTED,           "JOB_NOTIFY_FIELD_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
3379 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_BYTES,             "JOB_NOTIFY_FIELD_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
3380 };
3381
3382 /*******************************************************************
3383  Return the variable_type of info_data structure.
3384 ********************************************************************/
3385
3386 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3387                                                                   uint16_t field)
3388 {
3389         int i=0;
3390
3391         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3392                 if ( (notify_info_data_table[i].type == type) &&
3393                      (notify_info_data_table[i].field == field) ) {
3394                         return notify_info_data_table[i].variable_type;
3395                 }
3396         }
3397
3398         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3399
3400         return (enum spoolss_NotifyTable) 0;
3401 }
3402
3403 /****************************************************************************
3404 ****************************************************************************/
3405
3406 static bool search_notify(enum spoolss_NotifyType type,
3407                           uint16_t field,
3408                           int *value)
3409 {
3410         int i;
3411
3412         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3413                 if (notify_info_data_table[i].type == type &&
3414                     notify_info_data_table[i].field == field &&
3415                     notify_info_data_table[i].fn != NULL) {
3416                         *value = i;
3417                         return true;
3418                 }
3419         }
3420
3421         return false;
3422 }
3423
3424 /****************************************************************************
3425 ****************************************************************************/
3426
3427 static void construct_info_data(struct spoolss_Notify *info_data,
3428                                 enum spoolss_NotifyType type,
3429                                 uint16_t field, int id)
3430 {
3431         info_data->type                 = type;
3432         info_data->field.field          = field;
3433         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3434         info_data->job_id               = id;
3435 }
3436
3437 /*******************************************************************
3438  *
3439  * fill a notify_info struct with info asked
3440  *
3441  ********************************************************************/
3442
3443 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3444                                           struct printer_handle *print_hnd,
3445                                           struct spoolss_NotifyInfo *info,
3446                                           struct spoolss_PrinterInfo2 *pinfo2,
3447                                           int snum,
3448                                           const struct spoolss_NotifyOptionType *option_type,
3449                                           uint32_t id,
3450                                           TALLOC_CTX *mem_ctx)
3451 {
3452         int field_num,j;
3453         enum spoolss_NotifyType type;
3454         uint16_t field;
3455
3456         struct spoolss_Notify *current_data;
3457
3458         type = option_type->type;
3459
3460         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3461                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3462                 option_type->count, lp_servicename(snum)));
3463
3464         for(field_num=0; field_num < option_type->count; field_num++) {
3465                 field = option_type->fields[field_num].field;
3466
3467                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3468
3469                 if (!search_notify(type, field, &j) )
3470                         continue;
3471
3472                 info->notifies = talloc_realloc(info, info->notifies,
3473                                                       struct spoolss_Notify,
3474                                                       info->count + 1);
3475                 if (info->notifies == NULL) {
3476                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3477                         return false;
3478                 }
3479
3480                 current_data = &info->notifies[info->count];
3481
3482                 construct_info_data(current_data, type, field, id);
3483
3484                 DEBUG(10, ("construct_notify_printer_info: "
3485                            "calling [%s]  snum=%d  printername=[%s])\n",
3486                            notify_info_data_table[j].name, snum,
3487                            pinfo2->printername));
3488
3489                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3490                                              NULL, pinfo2, mem_ctx);
3491
3492                 info->count++;
3493         }
3494
3495         return true;
3496 }
3497
3498 /*******************************************************************
3499  *
3500  * fill a notify_info struct with info asked
3501  *
3502  ********************************************************************/
3503
3504 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3505                                        print_queue_struct *queue,
3506                                        struct spoolss_NotifyInfo *info,
3507                                        struct spoolss_PrinterInfo2 *pinfo2,
3508                                        int snum,
3509                                        const struct spoolss_NotifyOptionType *option_type,
3510                                        uint32_t id,
3511                                        TALLOC_CTX *mem_ctx)
3512 {
3513         int field_num,j;
3514         enum spoolss_NotifyType type;
3515         uint16_t field;
3516         struct spoolss_Notify *current_data;
3517
3518         DEBUG(4,("construct_notify_jobs_info\n"));
3519
3520         type = option_type->type;
3521
3522         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3523                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3524                 option_type->count));
3525
3526         for(field_num=0; field_num<option_type->count; field_num++) {
3527                 field = option_type->fields[field_num].field;
3528
3529                 if (!search_notify(type, field, &j) )
3530                         continue;
3531
3532                 info->notifies = talloc_realloc(info, info->notifies,
3533                                                       struct spoolss_Notify,
3534                                                       info->count + 1);
3535                 if (info->notifies == NULL) {
3536                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3537                         return false;
3538                 }
3539
3540                 current_data=&(info->notifies[info->count]);
3541
3542                 construct_info_data(current_data, type, field, id);
3543                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3544                                              queue, pinfo2, mem_ctx);
3545                 info->count++;
3546         }
3547
3548         return true;
3549 }
3550
3551 /*
3552  * JFM: The enumeration is not that simple, it's even non obvious.
3553  *
3554  * let's take an example: I want to monitor the PRINTER SERVER for
3555  * the printer's name and the number of jobs currently queued.
3556  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3557  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3558  *
3559  * I have 3 printers on the back of my server.
3560  *
3561  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3562  * structures.
3563  *   Number     Data                    Id
3564  *      1       printer 1 name          1
3565  *      2       printer 1 cjob          1
3566  *      3       printer 2 name          2
3567  *      4       printer 2 cjob          2
3568  *      5       printer 3 name          3
3569  *      6       printer 3 name          3
3570  *
3571  * that's the print server case, the printer case is even worse.
3572  */
3573
3574 /*******************************************************************
3575  *
3576  * enumerate all printers on the printserver
3577  * fill a notify_info struct with info asked
3578  *
3579  ********************************************************************/
3580
3581 static WERROR printserver_notify_info(struct pipes_struct *p,
3582                                       struct policy_handle *hnd,
3583                                       struct spoolss_NotifyInfo *info,
3584                                       TALLOC_CTX *mem_ctx)
3585 {
3586         int snum;
3587         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3588         int n_services=lp_numservices();
3589         int i;
3590         struct spoolss_NotifyOption *option;
3591         struct spoolss_NotifyOptionType option_type;
3592         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3593         WERROR result;
3594
3595         DEBUG(4,("printserver_notify_info\n"));
3596
3597         if (!Printer)
3598                 return WERR_BADFID;
3599
3600         option = Printer->notify.option;
3601
3602         info->version   = 2;
3603         info->notifies  = NULL;
3604         info->count     = 0;
3605
3606         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3607            sending a ffpcn() request first */
3608
3609         if ( !option )
3610                 return WERR_BADFID;
3611
3612         for (i=0; i<option->count; i++) {
3613                 option_type = option->types[i];
3614
3615                 if (option_type.type != PRINTER_NOTIFY_TYPE)
3616                         continue;
3617
3618                 for (snum = 0; snum < n_services; snum++) {
3619                         if (!lp_browseable(snum) ||
3620                             !lp_snum_ok(snum) ||
3621                             !lp_print_ok(snum)) {
3622                                 continue; /* skip */
3623                         }
3624
3625                         /* Maybe we should use the SYSTEM session_info here... */
3626                         result = winreg_get_printer_internal(mem_ctx,
3627                                                     get_session_info_system(),
3628                                                     p->msg_ctx,
3629                                                     lp_servicename(snum),
3630                                                     &pinfo2);
3631                         if (!W_ERROR_IS_OK(result)) {
3632                                 DEBUG(4, ("printserver_notify_info: "
3633                                           "Failed to get printer [%s]\n",
3634                                           lp_servicename(snum)));
3635                                 continue;
3636                         }
3637
3638
3639                         construct_notify_printer_info(p->msg_ctx,
3640                                                       Printer, info,
3641                                                       pinfo2, snum,
3642                                                       &option_type, snum,
3643                                                       mem_ctx);
3644
3645                         TALLOC_FREE(pinfo2);
3646                 }
3647         }
3648
3649 #if 0
3650         /*
3651          * Debugging information, don't delete.
3652          */
3653
3654         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3655         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3656         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3657
3658         for (i=0; i<info->count; i++) {
3659                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3660                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3661                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3662         }
3663 #endif
3664
3665         return WERR_OK;
3666 }
3667
3668 /*******************************************************************
3669  *
3670  * fill a notify_info struct with info asked
3671  *
3672  ********************************************************************/
3673
3674 static WERROR printer_notify_info(struct pipes_struct *p,
3675                                   struct policy_handle *hnd,
3676                                   struct spoolss_NotifyInfo *info,
3677                                   TALLOC_CTX *mem_ctx)
3678 {
3679         int snum;
3680         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3681         int i;
3682         uint32_t id;
3683         struct spoolss_NotifyOption *option;
3684         struct spoolss_NotifyOptionType option_type;
3685         int count,j;
3686         print_queue_struct *queue=NULL;
3687         print_status_struct status;
3688         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3689         WERROR result;
3690
3691         DEBUG(4,("printer_notify_info\n"));
3692
3693         if (!Printer)
3694                 return WERR_BADFID;
3695
3696         option = Printer->notify.option;
3697         id = 0x0;
3698
3699         info->version   = 2;
3700         info->notifies  = NULL;
3701         info->count     = 0;
3702
3703         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3704            sending a ffpcn() request first */
3705
3706         if ( !option )
3707                 return WERR_BADFID;
3708
3709         if (!get_printer_snum(p, hnd, &snum, NULL)) {
3710                 return WERR_BADFID;
3711         }
3712
3713         /* Maybe we should use the SYSTEM session_info here... */
3714         result = winreg_get_printer_internal(mem_ctx,
3715                                     get_session_info_system(),
3716                                     p->msg_ctx,
3717                                     lp_servicename(snum), &pinfo2);
3718         if (!W_ERROR_IS_OK(result)) {
3719                 return WERR_BADFID;
3720         }
3721
3722         for (i=0; i<option->count; i++) {
3723                 option_type = option->types[i];
3724
3725                 switch (option_type.type) {
3726                 case PRINTER_NOTIFY_TYPE:
3727                         if (construct_notify_printer_info(p->msg_ctx,
3728                                                           Printer, info,
3729                                                           pinfo2, snum,
3730                                                           &option_type, id,
3731                                                           mem_ctx)) {
3732                                 id--;
3733                         }
3734                         break;
3735
3736                 case JOB_NOTIFY_TYPE:
3737
3738                         count = print_queue_status(p->msg_ctx, snum, &queue,
3739                                                    &status);
3740
3741                         for (j=0; j<count; j++) {
3742                                 construct_notify_jobs_info(p->msg_ctx,
3743                                                            &queue[j], info,
3744                                                            pinfo2, snum,
3745                                                            &option_type,
3746                                                            queue[j].job,
3747                                                            mem_ctx);
3748                         }
3749
3750                         SAFE_FREE(queue);
3751                         break;
3752                 }
3753         }
3754
3755         /*
3756          * Debugging information, don't delete.
3757          */
3758         /*
3759         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3760         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3761         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3762
3763         for (i=0; i<info->count; i++) {
3764                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3765                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3766                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3767         }
3768         */
3769
3770         talloc_free(pinfo2);
3771         return WERR_OK;
3772 }
3773
3774 /****************************************************************
3775  _spoolss_RouterRefreshPrinterChangeNotify
3776 ****************************************************************/
3777
3778 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3779                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3780 {
3781         struct spoolss_NotifyInfo *info;
3782
3783         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3784         WERROR result = WERR_BADFID;
3785
3786         /* we always have a spoolss_NotifyInfo struct */
3787         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3788         if (!info) {
3789                 result = WERR_NOMEM;
3790                 goto done;
3791         }
3792
3793         *r->out.info = info;
3794
3795         if (!Printer) {
3796                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3797                         "Invalid handle (%s:%u:%u).\n",
3798                         OUR_HANDLE(r->in.handle)));
3799                 goto done;
3800         }
3801
3802         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3803
3804         /*
3805          *      We are now using the change value, and
3806          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3807          *      I don't have a global notification system, I'm sending back all the
3808          *      information even when _NOTHING_ has changed.
3809          */
3810
3811         /* We need to keep track of the change value to send back in
3812            RRPCN replies otherwise our updates are ignored. */
3813
3814         Printer->notify.fnpcn = true;
3815
3816         if (Printer->notify.cli_chan != NULL &&
3817             Printer->notify.cli_chan->active_connections > 0) {
3818                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3819                         "Saving change value in request [%x]\n",
3820                         r->in.change_low));
3821                 Printer->notify.change = r->in.change_low;
3822         }
3823
3824         /* just ignore the spoolss_NotifyOption */
3825
3826         switch (Printer->printer_type) {
3827                 case SPLHND_SERVER:
3828                         result = printserver_notify_info(p, r->in.handle,
3829                                                          info, p->mem_ctx);
3830                         break;
3831
3832                 case SPLHND_PRINTER:
3833                         result = printer_notify_info(p, r->in.handle,
3834                                                      info, p->mem_ctx);
3835                         break;
3836         }
3837
3838         Printer->notify.fnpcn = false;
3839
3840 done:
3841         return result;
3842 }
3843
3844 /********************************************************************
3845  ********************************************************************/
3846
3847 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3848                                  const char *servername,
3849                                  const char *printername,
3850                                  const char **printername_p)
3851 {
3852         /* FIXME: add lp_force_printername() */
3853
3854         if (servername == NULL) {
3855                 *printername_p = talloc_strdup(mem_ctx, printername);
3856                 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3857                 return WERR_OK;
3858         }
3859
3860         if (servername[0] == '\\' && servername[1] == '\\') {
3861                 servername += 2;
3862         }
3863
3864         *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3865         W_ERROR_HAVE_NO_MEMORY(*printername_p);
3866
3867         return WERR_OK;
3868 }
3869
3870 /********************************************************************
3871  ********************************************************************/
3872
3873 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3874                                           const char *printername)
3875 {
3876         if (dm == NULL) {
3877                 return;
3878         }
3879
3880         dm->devicename = talloc_strndup(dm, printername,
3881                                         MIN(strlen(printername), 31));
3882 }
3883
3884 /********************************************************************
3885  * construct_printer_info_0
3886  * fill a printer_info_0 struct
3887  ********************************************************************/
3888
3889 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3890                                       const struct auth_serversupplied_info *session_info,
3891                                       struct messaging_context *msg_ctx,
3892                                       struct spoolss_PrinterInfo2 *info2,
3893                                       const char *servername,
3894                                       struct spoolss_PrinterInfo0 *r,
3895                                       int snum)
3896 {
3897         int count;
3898         struct printer_session_counter *session_counter;
3899         struct timeval setuptime;
3900         print_status_struct status;
3901         WERROR result;
3902
3903         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3904         if (!W_ERROR_IS_OK(result)) {
3905                 return result;
3906         }
3907
3908         if (servername) {
3909                 r->servername = talloc_strdup(mem_ctx, servername);
3910                 W_ERROR_HAVE_NO_MEMORY(r->servername);
3911         } else {
3912                 r->servername = NULL;
3913         }
3914
3915         count = print_queue_length(msg_ctx, snum, &status);
3916
3917         /* check if we already have a counter for this printer */
3918         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3919                 if (session_counter->snum == snum)
3920                         break;
3921         }
3922
3923         /* it's the first time, add it to the list */
3924         if (session_counter == NULL) {
3925                 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3926                 W_ERROR_HAVE_NO_MEMORY(session_counter);
3927                 session_counter->snum           = snum;
3928                 session_counter->counter        = 0;
3929                 DLIST_ADD(counter_list, session_counter);
3930         }
3931
3932         /* increment it */
3933         session_counter->counter++;
3934
3935         r->cjobs                        = count;
3936         r->total_jobs                   = 0;
3937         r->total_bytes                  = 0;
3938
3939         get_startup_time(&setuptime);
3940         init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3941
3942         /* JFM:
3943          * the global_counter should be stored in a TDB as it's common to all the clients
3944          * and should be zeroed on samba startup
3945          */
3946         r->global_counter               = session_counter->counter;
3947         r->total_pages                  = 0;
3948         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3949         SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3950         SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3951         r->free_build                   = SPOOLSS_RELEASE_BUILD;
3952         r->spooling                     = 0;
3953         r->max_spooling                 = 0;
3954         r->session_counter              = session_counter->counter;
3955         r->num_error_out_of_paper       = 0x0;
3956         r->num_error_not_ready          = 0x0;          /* number of print failure */
3957         r->job_error                    = 0x0;
3958         r->number_of_processors         = 0x1;
3959         r->processor_type               = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3960         r->high_part_total_bytes        = 0x0;
3961
3962         /* ChangeID in milliseconds*/
3963         winreg_printer_get_changeid_internal(mem_ctx, session_info, msg_ctx,
3964                                     info2->sharename, &r->change_id);
3965
3966         r->last_error                   = WERR_OK;
3967         r->status                       = nt_printq_status(status.status);
3968         r->enumerate_network_printers   = 0x0;
3969         r->c_setprinter                 = 0x0;
3970         r->processor_architecture       = PROCESSOR_ARCHITECTURE_INTEL;
3971         r->processor_level              = 0x6;          /* 6  ???*/
3972         r->ref_ic                       = 0;
3973         r->reserved2                    = 0;
3974         r->reserved3                    = 0;
3975
3976         return WERR_OK;
3977 }
3978
3979
3980 /********************************************************************
3981  * construct_printer_info1
3982  * fill a spoolss_PrinterInfo1 struct
3983 ********************************************************************/
3984
3985 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3986                                       const struct spoolss_PrinterInfo2 *info2,
3987                                       uint32_t flags,
3988                                       const char *servername,
3989                                       struct spoolss_PrinterInfo1 *r,
3990                                       int snum)
3991 {
3992         WERROR result;
3993
3994         r->flags                = flags;
3995
3996         if (info2->comment == NULL || info2->comment[0] == '\0') {
3997                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
3998         } else {
3999                 r->comment      = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
4000         }
4001         W_ERROR_HAVE_NO_MEMORY(r->comment);
4002
4003         result = create_printername(mem_ctx, servername, info2->printername, &r->name);
4004         if (!W_ERROR_IS_OK(result)) {
4005                 return result;
4006         }
4007
4008         r->description          = talloc_asprintf(mem_ctx, "%s,%s,%s",
4009                                                   r->name,
4010                                                   info2->drivername,
4011                                                   r->comment);
4012         W_ERROR_HAVE_NO_MEMORY(r->description);
4013
4014         return WERR_OK;
4015 }
4016
4017 /********************************************************************
4018  * construct_printer_info2
4019  * fill a spoolss_PrinterInfo2 struct
4020 ********************************************************************/
4021
4022 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
4023                                       struct messaging_context *msg_ctx,
4024                                       const struct spoolss_PrinterInfo2 *info2,
4025                                       const char *servername,
4026                                       struct spoolss_PrinterInfo2 *r,
4027                                       int snum)
4028 {
4029         int count;
4030         print_status_struct status;
4031         WERROR result;
4032
4033         count = print_queue_length(msg_ctx, snum, &status);
4034
4035         if (servername) {
4036                 r->servername           = talloc_strdup(mem_ctx, servername);
4037                 W_ERROR_HAVE_NO_MEMORY(r->servername);
4038         } else {
4039                 r->servername           = NULL;
4040         }
4041
4042         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4043         if (!W_ERROR_IS_OK(result)) {
4044                 return result;
4045         }
4046
4047         r->sharename            = talloc_strdup(mem_ctx, lp_servicename(snum));
4048         W_ERROR_HAVE_NO_MEMORY(r->sharename);
4049         r->portname             = talloc_strdup(mem_ctx, info2->portname);
4050         W_ERROR_HAVE_NO_MEMORY(r->portname);
4051         r->drivername           = talloc_strdup(mem_ctx, info2->drivername);
4052         W_ERROR_HAVE_NO_MEMORY(r->drivername);
4053
4054         if (info2->comment[0] == '\0') {
4055                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
4056         } else {
4057                 r->comment      = talloc_strdup(mem_ctx, info2->comment);
4058         }
4059         W_ERROR_HAVE_NO_MEMORY(r->comment);
4060
4061         r->location     = talloc_strdup(mem_ctx, info2->location);
4062         if (info2->location[0] == '\0') {
4063                 const char *loc = NULL;
4064                 NTSTATUS nt_status;
4065
4066                 nt_status = printer_list_get_printer(mem_ctx,
4067                                                      info2->sharename,
4068                                                      NULL,
4069                                                      &loc,
4070                                                      NULL);
4071                 if (NT_STATUS_IS_OK(nt_status)) {
4072                         if (loc != NULL) {
4073                                 r->location = talloc_strdup(mem_ctx, loc);
4074                         }
4075                 }
4076         }
4077         W_ERROR_HAVE_NO_MEMORY(r->location);
4078
4079         r->sepfile              = talloc_strdup(mem_ctx, info2->sepfile);
4080         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4081         r->printprocessor       = talloc_strdup(mem_ctx, info2->printprocessor);
4082         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4083         r->datatype             = talloc_strdup(mem_ctx, info2->datatype);
4084         W_ERROR_HAVE_NO_MEMORY(r->datatype);
4085         r->parameters           = talloc_strdup(mem_ctx, info2->parameters);
4086         W_ERROR_HAVE_NO_MEMORY(r->parameters);
4087
4088         r->attributes           = info2->attributes;
4089
4090         r->priority             = info2->priority;
4091         r->defaultpriority      = info2->defaultpriority;
4092         r->starttime            = info2->starttime;
4093         r->untiltime            = info2->untiltime;
4094         r->status               = nt_printq_status(status.status);
4095         r->cjobs                = count;
4096         r->averageppm           = info2->averageppm;
4097
4098         copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4099         if (!r->devmode) {
4100                 DEBUG(8,("Returning NULL Devicemode!\n"));
4101         }
4102
4103         compose_devicemode_devicename(r->devmode, r->printername);
4104
4105         r->secdesc = NULL;
4106
4107         if (info2->secdesc != NULL) {
4108                 /* don't use talloc_steal() here unless you do a deep steal of all
4109                    the SEC_DESC members */
4110
4111                 r->secdesc      = dup_sec_desc(mem_ctx, info2->secdesc);
4112         }
4113
4114         return WERR_OK;
4115 }
4116
4117 /********************************************************************
4118  * construct_printer_info3
4119  * fill a spoolss_PrinterInfo3 struct
4120  ********************************************************************/
4121
4122 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4123                                       const struct spoolss_PrinterInfo2 *info2,
4124                                       const char *servername,
4125                                       struct spoolss_PrinterInfo3 *r,
4126                                       int snum)
4127 {
4128         /* These are the components of the SD we are returning. */
4129
4130         if (info2->secdesc != NULL) {
4131                 /* don't use talloc_steal() here unless you do a deep steal of all
4132                    the SEC_DESC members */
4133
4134                 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4135                 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
4136         }
4137
4138         return WERR_OK;
4139 }
4140
4141 /********************************************************************
4142  * construct_printer_info4
4143  * fill a spoolss_PrinterInfo4 struct
4144  ********************************************************************/
4145
4146 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4147                                       const struct spoolss_PrinterInfo2 *info2,
4148                                       const char *servername,
4149                                       struct spoolss_PrinterInfo4 *r,
4150                                       int snum)
4151 {
4152         WERROR result;
4153
4154         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4155         if (!W_ERROR_IS_OK(result)) {
4156                 return result;
4157         }
4158
4159         if (servername) {
4160                 r->servername   = talloc_strdup(mem_ctx, servername);
4161                 W_ERROR_HAVE_NO_MEMORY(r->servername);
4162         } else {
4163                 r->servername = NULL;
4164         }
4165
4166         r->attributes   = info2->attributes;
4167
4168         return WERR_OK;
4169 }
4170
4171 /********************************************************************
4172  * construct_printer_info5
4173  * fill a spoolss_PrinterInfo5 struct
4174  ********************************************************************/
4175
4176 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4177                                       const struct spoolss_PrinterInfo2 *info2,
4178                                       const char *servername,
4179                                       struct spoolss_PrinterInfo5 *r,
4180                                       int snum)
4181 {
4182         WERROR result;
4183
4184         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4185         if (!W_ERROR_IS_OK(result)) {
4186                 return result;
4187         }
4188
4189         r->portname     = talloc_strdup(mem_ctx, info2->portname);
4190         W_ERROR_HAVE_NO_MEMORY(r->portname);
4191
4192         r->attributes   = info2->attributes;
4193
4194         /* these two are not used by NT+ according to MSDN */
4195         r->device_not_selected_timeout          = 0x0;  /* have seen 0x3a98 */
4196         r->transmission_retry_timeout           = 0x0;  /* have seen 0xafc8 */
4197
4198         return WERR_OK;
4199 }
4200
4201 /********************************************************************
4202  * construct_printer_info_6
4203  * fill a spoolss_PrinterInfo6 struct
4204  ********************************************************************/
4205
4206 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4207                                       struct messaging_context *msg_ctx,
4208                                       const struct spoolss_PrinterInfo2 *info2,
4209                                       const char *servername,
4210                                       struct spoolss_PrinterInfo6 *r,
4211                                       int snum)
4212 {
4213         print_status_struct status;
4214
4215         print_queue_length(msg_ctx, snum, &status);
4216
4217         r->status = nt_printq_status(status.status);
4218
4219         return WERR_OK;
4220 }
4221
4222 /********************************************************************
4223  * construct_printer_info7
4224  * fill a spoolss_PrinterInfo7 struct
4225  ********************************************************************/
4226
4227 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4228                                       struct messaging_context *msg_ctx,
4229                                       const char *servername,
4230                                       struct spoolss_PrinterInfo7 *r,
4231                                       int snum)
4232 {
4233         struct auth_serversupplied_info *session_info;
4234         struct GUID guid;
4235         NTSTATUS status;
4236
4237         status = make_session_info_system(mem_ctx, &session_info);
4238         if (!NT_STATUS_IS_OK(status)) {
4239                 DEBUG(0, ("construct_printer_info7: "
4240                           "Could not create system session_info\n"));
4241                 return WERR_NOMEM;
4242         }
4243
4244         if (is_printer_published(mem_ctx, session_info, msg_ctx,
4245                                  servername,
4246                                  lp_servicename(snum), &guid, NULL)) {
4247                 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4248                 r->action = DSPRINT_PUBLISH;
4249         } else {
4250                 r->guid = talloc_strdup(mem_ctx, "");
4251                 r->action = DSPRINT_UNPUBLISH;
4252         }
4253         W_ERROR_HAVE_NO_MEMORY(r->guid);
4254
4255         TALLOC_FREE(session_info);
4256         return WERR_OK;
4257 }
4258
4259 /********************************************************************
4260  * construct_printer_info8
4261  * fill a spoolss_PrinterInfo8 struct
4262  ********************************************************************/
4263
4264 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4265                                       const struct spoolss_PrinterInfo2 *info2,
4266                                       const char *servername,
4267                                       struct spoolss_DeviceModeInfo *r,
4268                                       int snum)
4269 {
4270         WERROR result;
4271         const char *printername;
4272
4273         result = create_printername(mem_ctx, servername, info2->printername, &printername);
4274         if (!W_ERROR_IS_OK(result)) {
4275                 return result;
4276         }
4277
4278         copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4279         if (!r->devmode) {
4280                 DEBUG(8,("Returning NULL Devicemode!\n"));
4281         }
4282
4283         compose_devicemode_devicename(r->devmode, printername);
4284
4285         return WERR_OK;
4286 }
4287
4288
4289 /********************************************************************
4290 ********************************************************************/
4291
4292 static bool snum_is_shared_printer(int snum)
4293 {
4294         return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4295 }
4296
4297 /********************************************************************
4298  Spoolss_enumprinters.
4299 ********************************************************************/
4300
4301 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4302                                            const struct auth_serversupplied_info *session_info,
4303                                            struct messaging_context *msg_ctx,
4304                                            const char *servername,
4305                                            uint32_t level,
4306                                            uint32_t flags,
4307                                            union spoolss_PrinterInfo **info_p,
4308                                            uint32_t *count_p)
4309 {
4310         int snum;
4311         int n_services = lp_numservices();
4312         union spoolss_PrinterInfo *info = NULL;
4313         uint32_t count = 0;
4314         WERROR result = WERR_OK;
4315         struct dcerpc_binding_handle *b = NULL;
4316
4317         *count_p = 0;
4318         *info_p = NULL;
4319
4320         for (snum = 0; snum < n_services; snum++) {
4321
4322                 const char *printer;
4323                 struct spoolss_PrinterInfo2 *info2;
4324
4325                 if (!snum_is_shared_printer(snum)) {
4326                         continue;
4327                 }
4328
4329                 printer = lp_const_servicename(snum);
4330
4331                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4332                         printer, snum));
4333
4334                 if (b == NULL) {
4335                         result = winreg_printer_binding_handle(mem_ctx,
4336                                                                session_info,
4337                                                                msg_ctx,
4338                                                                &b);
4339                         if (!W_ERROR_IS_OK(result)) {
4340                                 goto out;
4341                         }
4342                 }
4343
4344                 result = winreg_create_printer(mem_ctx, b,
4345                                                printer);
4346                 if (!W_ERROR_IS_OK(result)) {
4347                         goto out;
4348                 }
4349
4350                 info = talloc_realloc(mem_ctx, info,
4351                                             union spoolss_PrinterInfo,
4352                                             count + 1);
4353                 if (!info) {
4354                         result = WERR_NOMEM;
4355                         goto out;
4356                 }
4357
4358                 result = winreg_get_printer(mem_ctx, b,
4359                                             printer, &info2);
4360                 if (!W_ERROR_IS_OK(result)) {
4361                         goto out;
4362                 }
4363
4364                 switch (level) {
4365                 case 0:
4366                         result = construct_printer_info0(info, session_info,
4367                                                          msg_ctx, info2,
4368                                                          servername,
4369                                                          &info[count].info0, snum);
4370                         break;
4371                 case 1:
4372                         result = construct_printer_info1(info, info2, flags,
4373                                                          servername,
4374                                                          &info[count].info1, snum);
4375                         break;
4376                 case 2:
4377                         result = construct_printer_info2(info, msg_ctx, info2,
4378                                                          servername,
4379                                                          &info[count].info2, snum);
4380                         break;
4381                 case 4:
4382                         result = construct_printer_info4(info, info2,
4383                                                          servername,
4384                                                          &info[count].info4, snum);
4385                         break;
4386                 case 5:
4387                         result = construct_printer_info5(info, info2,
4388                                                          servername,
4389                                                          &info[count].info5, snum);
4390                         break;
4391
4392                 default:
4393                         result = WERR_UNKNOWN_LEVEL;
4394                         goto out;
4395                 }
4396
4397                 if (!W_ERROR_IS_OK(result)) {
4398                         goto out;
4399                 }
4400
4401                 count++;
4402         }
4403
4404         *count_p = count;
4405         *info_p = info;
4406
4407  out:
4408         if (!W_ERROR_IS_OK(result)) {
4409                 TALLOC_FREE(info);
4410                 return result;
4411         }
4412
4413         *info_p = info;
4414
4415         return WERR_OK;
4416 }
4417
4418 /********************************************************************
4419  * handle enumeration of printers at level 0
4420  ********************************************************************/
4421
4422 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4423                                   const struct auth_serversupplied_info *session_info,
4424                                   struct messaging_context *msg_ctx,
4425                                   uint32_t flags,
4426                                   const char *servername,
4427                                   union spoolss_PrinterInfo **info,
4428                                   uint32_t *count)
4429 {
4430         DEBUG(4,("enum_all_printers_info_0\n"));
4431
4432         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4433                                             servername, 0, flags, info, count);
4434 }
4435
4436
4437 /********************************************************************
4438 ********************************************************************/
4439
4440 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4441                                        const struct auth_serversupplied_info *session_info,
4442                                        struct messaging_context *msg_ctx,
4443                                        const char *servername,
4444                                        uint32_t flags,
4445                                        union spoolss_PrinterInfo **info,
4446                                        uint32_t *count)
4447 {
4448         DEBUG(4,("enum_all_printers_info_1\n"));
4449
4450         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4451                                             servername, 1, flags, info, count);
4452 }
4453
4454 /********************************************************************
4455  enum_all_printers_info_1_local.
4456 *********************************************************************/
4457
4458 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4459                                              const struct auth_serversupplied_info *session_info,
4460                                              struct messaging_context *msg_ctx,
4461                                              const char *servername,
4462                                              union spoolss_PrinterInfo **info,
4463                                              uint32_t *count)
4464 {
4465         DEBUG(4,("enum_all_printers_info_1_local\n"));
4466
4467         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4468                                         servername, PRINTER_ENUM_ICON8, info, count);
4469 }
4470
4471 /********************************************************************
4472  enum_all_printers_info_1_name.
4473 *********************************************************************/
4474
4475 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4476                                             const struct auth_serversupplied_info *session_info,
4477                                             struct messaging_context *msg_ctx,
4478                                             const char *servername,
4479                                             union spoolss_PrinterInfo **info,
4480                                             uint32_t *count)
4481 {
4482         const char *s = servername;
4483
4484         DEBUG(4,("enum_all_printers_info_1_name\n"));
4485
4486         if ((servername[0] == '\\') && (servername[1] == '\\')) {
4487                 s = servername + 2;
4488         }
4489
4490         if (!is_myname_or_ipaddr(s)) {
4491                 return WERR_INVALID_NAME;
4492         }
4493
4494         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4495                                         servername, PRINTER_ENUM_ICON8, info, count);
4496 }
4497
4498 /********************************************************************
4499  enum_all_printers_info_1_network.
4500 *********************************************************************/
4501
4502 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4503                                                const struct auth_serversupplied_info *session_info,
4504                                                struct messaging_context *msg_ctx,
4505                                                const char *servername,
4506                                                union spoolss_PrinterInfo **info,
4507                                                uint32_t *count)
4508 {
4509         const char *s = servername;
4510
4511         DEBUG(4,("enum_all_printers_info_1_network\n"));
4512
4513         /* If we respond to a enum_printers level 1 on our name with flags
4514            set to PRINTER_ENUM_REMOTE with a list of printers then these
4515            printers incorrectly appear in the APW browse list.
4516            Specifically the printers for the server appear at the workgroup
4517            level where all the other servers in the domain are
4518            listed. Windows responds to this call with a
4519            WERR_CAN_NOT_COMPLETE so we should do the same. */
4520
4521         if (servername[0] == '\\' && servername[1] == '\\') {
4522                  s = servername + 2;
4523         }
4524
4525         if (is_myname_or_ipaddr(s)) {
4526                  return WERR_CAN_NOT_COMPLETE;
4527         }
4528
4529         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4530                                         servername, PRINTER_ENUM_NAME, info, count);
4531 }
4532
4533 /********************************************************************
4534  * api_spoolss_enumprinters
4535  *
4536  * called from api_spoolss_enumprinters (see this to understand)
4537  ********************************************************************/
4538
4539 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4540                                        const struct auth_serversupplied_info *session_info,
4541                                        struct messaging_context *msg_ctx,
4542                                        const char *servername,
4543                                        union spoolss_PrinterInfo **info,
4544                                        uint32_t *count)
4545 {
4546         DEBUG(4,("enum_all_printers_info_2\n"));
4547
4548         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4549                                             servername, 2, 0, info, count);
4550 }
4551
4552 /********************************************************************
4553  * handle enumeration of printers at level 1
4554  ********************************************************************/
4555
4556 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4557                                   const struct auth_serversupplied_info *session_info,
4558                                   struct messaging_context *msg_ctx,
4559                                   uint32_t flags,
4560                                   const char *servername,
4561                                   union spoolss_PrinterInfo **info,
4562                                   uint32_t *count)
4563 {
4564         /* Not all the flags are equals */
4565
4566         if (flags & PRINTER_ENUM_LOCAL) {
4567                 return enum_all_printers_info_1_local(mem_ctx, session_info,
4568                                                       msg_ctx, servername, info, count);
4569         }
4570
4571         if (flags & PRINTER_ENUM_NAME) {
4572                 return enum_all_printers_info_1_name(mem_ctx, session_info,
4573                                                      msg_ctx, servername, info,
4574                                                      count);
4575         }
4576
4577         if (flags & PRINTER_ENUM_NETWORK) {
4578                 return enum_all_printers_info_1_network(mem_ctx, session_info,
4579                                                         msg_ctx, servername, info,
4580                                                         count);
4581         }
4582
4583         return WERR_OK; /* NT4sp5 does that */
4584 }
4585
4586 /********************************************************************
4587  * handle enumeration of printers at level 2
4588  ********************************************************************/
4589
4590 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4591                                   const struct auth_serversupplied_info *session_info,
4592                                   struct messaging_context *msg_ctx,
4593                                   uint32_t flags,
4594                                   const char *servername,
4595                                   union spoolss_PrinterInfo **info,
4596                                   uint32_t *count)
4597 {
4598         if (flags & PRINTER_ENUM_LOCAL) {
4599
4600                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4601                                                 servername,
4602                                                 info, count);
4603         }
4604
4605         if (flags & PRINTER_ENUM_NAME) {
4606                 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4607                         return WERR_INVALID_NAME;
4608                 }
4609
4610                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4611                                                 servername,
4612                                                 info, count);
4613         }
4614
4615         if (flags & PRINTER_ENUM_REMOTE) {
4616                 return WERR_UNKNOWN_LEVEL;
4617         }
4618
4619         return WERR_OK;
4620 }
4621
4622 /********************************************************************
4623  * handle enumeration of printers at level 4
4624  ********************************************************************/
4625
4626 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4627                                   const struct auth_serversupplied_info *session_info,
4628                                   struct messaging_context *msg_ctx,
4629                                   uint32_t flags,
4630                                   const char *servername,
4631                                   union spoolss_PrinterInfo **info,
4632                                   uint32_t *count)
4633 {
4634         DEBUG(4,("enum_all_printers_info_4\n"));
4635
4636         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4637                                             servername, 4, flags, info, count);
4638 }
4639
4640
4641 /********************************************************************
4642  * handle enumeration of printers at level 5
4643  ********************************************************************/
4644
4645 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4646                                   const struct auth_serversupplied_info *session_info,
4647                                   struct messaging_context *msg_ctx,
4648                                   uint32_t flags,
4649                                   const char *servername,
4650                                   union spoolss_PrinterInfo **info,
4651                                   uint32_t *count)
4652 {
4653         DEBUG(4,("enum_all_printers_info_5\n"));
4654
4655         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4656                                             servername, 5, flags, info, count);
4657 }
4658
4659 /****************************************************************
4660  _spoolss_EnumPrinters
4661 ****************************************************************/
4662
4663 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4664                              struct spoolss_EnumPrinters *r)
4665 {
4666         const struct auth_serversupplied_info *session_info = get_session_info_system();
4667         WERROR result;
4668
4669         /* that's an [in out] buffer */
4670
4671         if (!r->in.buffer && (r->in.offered != 0)) {
4672                 return WERR_INVALID_PARAM;
4673         }
4674
4675         DEBUG(4,("_spoolss_EnumPrinters\n"));
4676
4677         *r->out.needed = 0;
4678         *r->out.count = 0;
4679         *r->out.info = NULL;
4680
4681         /*
4682          * Level 1:
4683          *          flags==PRINTER_ENUM_NAME
4684          *           if name=="" then enumerates all printers
4685          *           if name!="" then enumerate the printer
4686          *          flags==PRINTER_ENUM_REMOTE
4687          *          name is NULL, enumerate printers
4688          * Level 2: name!="" enumerates printers, name can't be NULL
4689          * Level 3: doesn't exist
4690          * Level 4: does a local registry lookup
4691          * Level 5: same as Level 2
4692          */
4693
4694         if (r->in.server && r->in.server[0] == '\0') {
4695                 r->in.server = NULL;
4696         }
4697
4698         switch (r->in.level) {
4699         case 0:
4700                 result = enumprinters_level0(p->mem_ctx, session_info,
4701                                              p->msg_ctx, r->in.flags,
4702                                              r->in.server,
4703                                              r->out.info, r->out.count);
4704                 break;
4705         case 1:
4706                 result = enumprinters_level1(p->mem_ctx, session_info,
4707                                              p->msg_ctx, r->in.flags,
4708                                              r->in.server,
4709                                              r->out.info, r->out.count);
4710                 break;
4711         case 2:
4712                 result = enumprinters_level2(p->mem_ctx, session_info,
4713                                              p->msg_ctx, r->in.flags,
4714                                              r->in.server,
4715                                              r->out.info, r->out.count);
4716                 break;
4717         case 4:
4718                 result = enumprinters_level4(p->mem_ctx, session_info,
4719                                              p->msg_ctx, r->in.flags,
4720                                              r->in.server,
4721                                              r->out.info, r->out.count);
4722                 break;
4723         case 5:
4724                 result = enumprinters_level5(p->mem_ctx, session_info,
4725                                              p->msg_ctx, r->in.flags,
4726                                              r->in.server,
4727                                              r->out.info, r->out.count);
4728                 break;
4729         default:
4730                 return WERR_UNKNOWN_LEVEL;
4731         }
4732
4733         if (!W_ERROR_IS_OK(result)) {
4734                 return result;
4735         }
4736
4737         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4738                                                      spoolss_EnumPrinters,
4739                                                      *r->out.info, r->in.level,
4740                                                      *r->out.count);
4741         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4742         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4743
4744         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4745 }
4746
4747 /****************************************************************
4748  _spoolss_GetPrinter
4749 ****************************************************************/
4750
4751 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4752                            struct spoolss_GetPrinter *r)
4753 {
4754         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4755         struct spoolss_PrinterInfo2 *info2 = NULL;
4756         WERROR result = WERR_OK;
4757         int snum;
4758
4759         /* that's an [in out] buffer */
4760
4761         if (!r->in.buffer && (r->in.offered != 0)) {
4762                 return WERR_INVALID_PARAM;
4763         }
4764
4765         *r->out.needed = 0;
4766
4767         if (Printer == NULL) {
4768                 return WERR_BADFID;
4769         }
4770
4771         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4772                 return WERR_BADFID;
4773         }
4774
4775         result = winreg_get_printer_internal(p->mem_ctx,
4776                                     get_session_info_system(),
4777                                     p->msg_ctx,
4778                                     lp_const_servicename(snum),
4779                                     &info2);
4780         if (!W_ERROR_IS_OK(result)) {
4781                 goto out;
4782         }
4783
4784         switch (r->in.level) {
4785         case 0:
4786                 result = construct_printer_info0(p->mem_ctx,
4787                                                  get_session_info_system(),
4788                                                  p->msg_ctx,
4789                                                  info2,
4790                                                  Printer->servername,
4791                                                  &r->out.info->info0,
4792                                                  snum);
4793                 break;
4794         case 1:
4795                 result = construct_printer_info1(p->mem_ctx, info2,
4796                                                  PRINTER_ENUM_ICON8,
4797                                                  Printer->servername,
4798                                                  &r->out.info->info1, snum);
4799                 break;
4800         case 2:
4801                 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4802                                                  Printer->servername,
4803                                                  &r->out.info->info2, snum);
4804                 break;
4805         case 3:
4806                 result = construct_printer_info3(p->mem_ctx, info2,
4807                                                  Printer->servername,
4808                                                  &r->out.info->info3, snum);
4809                 break;
4810         case 4:
4811                 result = construct_printer_info4(p->mem_ctx, info2,
4812                                                  Printer->servername,
4813                                                  &r->out.info->info4, snum);
4814                 break;
4815         case 5:
4816                 result = construct_printer_info5(p->mem_ctx, info2,
4817                                                  Printer->servername,
4818                                                  &r->out.info->info5, snum);
4819                 break;
4820         case 6:
4821                 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4822                                                  Printer->servername,
4823                                                  &r->out.info->info6, snum);
4824                 break;
4825         case 7:
4826                 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4827                                                  Printer->servername,
4828                                                  &r->out.info->info7, snum);
4829                 break;
4830         case 8:
4831                 result = construct_printer_info8(p->mem_ctx, info2,
4832                                                  Printer->servername,
4833                                                  &r->out.info->info8, snum);
4834                 break;
4835         default:
4836                 result = WERR_UNKNOWN_LEVEL;
4837                 break;
4838         }
4839
4840  out:
4841         if (!W_ERROR_IS_OK(result)) {
4842                 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4843                           r->in.level, win_errstr(result)));
4844                 TALLOC_FREE(r->out.info);
4845                 return result;
4846         }
4847
4848         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4849                                                r->out.info, r->in.level);
4850         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4851
4852         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4853 }
4854
4855 /********************************************************************
4856  ********************************************************************/
4857
4858 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4859         do { \
4860                 if (in && strlen(in)) { \
4861                         out = talloc_strdup(mem_ctx, in); \
4862                 } else { \
4863                         out = talloc_strdup(mem_ctx, ""); \
4864                 } \
4865                 W_ERROR_HAVE_NO_MEMORY(out); \
4866         } while (0);
4867
4868 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4869         do { \
4870                 if (in && strlen(in)) { \
4871                         out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4872                 } else { \
4873                         out = talloc_strdup(mem_ctx, ""); \
4874                 } \
4875                 W_ERROR_HAVE_NO_MEMORY(out); \
4876         } while (0);
4877
4878 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4879                                                   const char **string_array,
4880                                                   const char ***presult,
4881                                                   const char *cservername,
4882                                                   const char *arch,
4883                                                   int version)
4884 {
4885         int i, num_strings = 0;
4886         const char **array = NULL;
4887
4888         if (string_array == NULL) {
4889                 return WERR_INVALID_PARAMETER;
4890         }
4891
4892         for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4893                 const char *str = NULL;
4894
4895                 if (cservername == NULL || arch == NULL) {
4896                         FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4897                 } else {
4898                         FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4899                 }
4900
4901                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4902                         TALLOC_FREE(array);
4903                         return WERR_NOMEM;
4904                 }
4905         }
4906
4907         if (i > 0) {
4908                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4909                              &array, &num_strings);
4910         }
4911
4912         if (presult) {
4913                 *presult = array;
4914         }
4915
4916         return WERR_OK;
4917 }
4918
4919 /********************************************************************
4920  * fill a spoolss_DriverInfo1 struct
4921  ********************************************************************/
4922
4923 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4924                                         struct spoolss_DriverInfo1 *r,
4925                                         const struct spoolss_DriverInfo8 *driver,
4926                                         const char *servername)
4927 {
4928         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4929         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4930
4931         return WERR_OK;
4932 }
4933
4934 /********************************************************************
4935  * fill a spoolss_DriverInfo2 struct
4936  ********************************************************************/
4937
4938 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4939                                         struct spoolss_DriverInfo2 *r,
4940                                         const struct spoolss_DriverInfo8 *driver,
4941                                         const char *servername)
4942
4943 {
4944         const char *cservername = canon_servername(servername);
4945
4946         r->version              = driver->version;
4947
4948         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4949         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4950         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4951         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4952
4953         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4954                                driver->architecture,
4955                                driver->version,
4956                                driver->driver_path,
4957                                r->driver_path);
4958
4959         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4960                                driver->architecture,
4961                                driver->version,
4962                                driver->data_file,
4963                                r->data_file);
4964
4965         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4966                                driver->architecture,
4967                                driver->version,
4968                                driver->config_file,
4969                                r->config_file);
4970
4971         return WERR_OK;
4972 }
4973
4974 /********************************************************************
4975  * fill a spoolss_DriverInfo3 struct
4976  ********************************************************************/
4977
4978 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4979                                         struct spoolss_DriverInfo3 *r,
4980                                         const struct spoolss_DriverInfo8 *driver,
4981                                         const char *servername)
4982 {
4983         const char *cservername = canon_servername(servername);
4984
4985         r->version              = driver->version;
4986
4987         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4988         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4989         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4990         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4991
4992         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4993                                driver->architecture,
4994                                driver->version,
4995                                driver->driver_path,
4996                                r->driver_path);
4997
4998         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4999                                driver->architecture,
5000                                driver->version,
5001                                driver->data_file,
5002                                r->data_file);
5003
5004         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5005                                driver->architecture,
5006                                driver->version,
5007                                driver->config_file,
5008                                r->config_file);
5009
5010         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5011                                driver->architecture,
5012                                driver->version,
5013                                driver->help_file,
5014                                r->help_file);
5015
5016         FILL_DRIVER_STRING(mem_ctx,
5017                            driver->monitor_name,
5018                            r->monitor_name);
5019
5020         FILL_DRIVER_STRING(mem_ctx,
5021                            driver->default_datatype,
5022                            r->default_datatype);
5023
5024         return string_array_from_driver_info(mem_ctx,
5025                                              driver->dependent_files,
5026                                              &r->dependent_files,
5027                                              cservername,
5028                                              driver->architecture,
5029                                              driver->version);
5030 }
5031
5032 /********************************************************************
5033  * fill a spoolss_DriverInfo4 struct
5034  ********************************************************************/
5035
5036 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
5037                                         struct spoolss_DriverInfo4 *r,
5038                                         const struct spoolss_DriverInfo8 *driver,
5039                                         const char *servername)
5040 {
5041         const char *cservername = canon_servername(servername);
5042         WERROR result;
5043
5044         r->version              = driver->version;
5045
5046         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5047         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5048         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5049         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5050
5051         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5052                                driver->architecture,
5053                                driver->version,
5054                                driver->driver_path,
5055                                r->driver_path);
5056
5057         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5058                                driver->architecture,
5059                                driver->version,
5060                                driver->data_file,
5061                                r->data_file);
5062
5063         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5064                                driver->architecture,
5065                                driver->version,
5066                                driver->config_file,
5067                                r->config_file);
5068
5069         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5070                                driver->architecture,
5071                                driver->version,
5072                                driver->help_file,
5073                                r->help_file);
5074
5075         result = string_array_from_driver_info(mem_ctx,
5076                                                driver->dependent_files,
5077                                                &r->dependent_files,
5078                                                cservername,
5079                                                driver->architecture,
5080                                                driver->version);
5081         if (!W_ERROR_IS_OK(result)) {
5082                 return result;
5083         }
5084
5085         FILL_DRIVER_STRING(mem_ctx,
5086                            driver->monitor_name,
5087                            r->monitor_name);
5088
5089         FILL_DRIVER_STRING(mem_ctx,
5090                            driver->default_datatype,
5091                            r->default_datatype);
5092
5093
5094         result = string_array_from_driver_info(mem_ctx,
5095                                                driver->previous_names,
5096                                                &r->previous_names,
5097                                                NULL, NULL, 0);
5098
5099         return result;
5100 }
5101
5102 /********************************************************************
5103  * fill a spoolss_DriverInfo5 struct
5104  ********************************************************************/
5105
5106 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5107                                         struct spoolss_DriverInfo5 *r,
5108                                         const struct spoolss_DriverInfo8 *driver,
5109                                         const char *servername)
5110 {
5111         const char *cservername = canon_servername(servername);
5112
5113         r->version              = driver->version;
5114
5115         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5116         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5117         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5118         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5119
5120         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5121                                driver->architecture,
5122                                driver->version,
5123                                driver->driver_path,
5124                                r->driver_path);
5125
5126         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5127                                driver->architecture,
5128                                driver->version,
5129                                driver->data_file,
5130                                r->data_file);
5131
5132         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5133                                driver->architecture,
5134                                driver->version,
5135                                driver->config_file,
5136                                r->config_file);
5137
5138         r->driver_attributes    = 0;
5139         r->config_version       = 0;
5140         r->driver_version       = 0;
5141
5142         return WERR_OK;
5143 }
5144 /********************************************************************
5145  * fill a spoolss_DriverInfo6 struct
5146  ********************************************************************/
5147
5148 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5149                                         struct spoolss_DriverInfo6 *r,
5150                                         const struct spoolss_DriverInfo8 *driver,
5151                                         const char *servername)
5152 {
5153         const char *cservername = canon_servername(servername);
5154         WERROR result;
5155
5156         r->version              = driver->version;
5157
5158         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5159         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5160         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5161         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5162
5163         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5164                                driver->architecture,
5165                                driver->version,
5166                                driver->driver_path,
5167                                r->driver_path);
5168
5169         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5170                                driver->architecture,
5171                                driver->version,
5172                                driver->data_file,
5173                                r->data_file);
5174
5175         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5176                                driver->architecture,
5177                                driver->version,
5178                                driver->config_file,
5179                                r->config_file);
5180
5181         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5182                                driver->architecture,
5183                                driver->version,
5184                                driver->help_file,
5185                                r->help_file);
5186
5187         FILL_DRIVER_STRING(mem_ctx,
5188                            driver->monitor_name,
5189                            r->monitor_name);
5190
5191         FILL_DRIVER_STRING(mem_ctx,
5192                            driver->default_datatype,
5193                            r->default_datatype);
5194
5195         result = string_array_from_driver_info(mem_ctx,
5196                                                driver->dependent_files,
5197                                                &r->dependent_files,
5198                                                cservername,
5199                                                driver->architecture,
5200                                                driver->version);
5201         if (!W_ERROR_IS_OK(result)) {
5202                 return result;
5203         }
5204
5205         result = string_array_from_driver_info(mem_ctx,
5206                                                driver->previous_names,
5207                                                &r->previous_names,
5208                                                NULL, NULL, 0);
5209         if (!W_ERROR_IS_OK(result)) {
5210                 return result;
5211         }
5212
5213         r->driver_date          = driver->driver_date;
5214         r->driver_version       = driver->driver_version;
5215
5216         FILL_DRIVER_STRING(mem_ctx,
5217                            driver->manufacturer_name,
5218                            r->manufacturer_name);
5219         FILL_DRIVER_STRING(mem_ctx,
5220                            driver->manufacturer_url,
5221                            r->manufacturer_url);
5222         FILL_DRIVER_STRING(mem_ctx,
5223                            driver->hardware_id,
5224                            r->hardware_id);
5225         FILL_DRIVER_STRING(mem_ctx,
5226                            driver->provider,
5227                            r->provider);
5228
5229         return WERR_OK;
5230 }
5231
5232 /********************************************************************
5233  * fill a spoolss_DriverInfo8 struct
5234  ********************************************************************/
5235
5236 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5237                                         struct spoolss_DriverInfo8 *r,
5238                                         const struct spoolss_DriverInfo8 *driver,
5239                                         const char *servername)
5240 {
5241         const char *cservername = canon_servername(servername);
5242         WERROR result;
5243
5244         r->version              = driver->version;
5245
5246         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5247         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5248         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5249         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5250
5251         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5252                                driver->architecture,
5253                                driver->version,
5254                                driver->driver_path,
5255                                r->driver_path);
5256
5257         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5258                                driver->architecture,
5259                                driver->version,
5260                                driver->data_file,
5261                                r->data_file);
5262
5263         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5264                                driver->architecture,
5265                                driver->version,
5266                                driver->config_file,
5267                                r->config_file);
5268
5269         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5270                                driver->architecture,
5271                                driver->version,
5272                                driver->help_file,
5273                                r->help_file);
5274
5275         FILL_DRIVER_STRING(mem_ctx,
5276                            driver->monitor_name,
5277                            r->monitor_name);
5278
5279         FILL_DRIVER_STRING(mem_ctx,
5280                            driver->default_datatype,
5281                            r->default_datatype);
5282
5283         result = string_array_from_driver_info(mem_ctx,
5284                                                driver->dependent_files,
5285                                                &r->dependent_files,
5286                                                cservername,
5287                                                driver->architecture,
5288                                                driver->version);
5289         if (!W_ERROR_IS_OK(result)) {
5290                 return result;
5291         }
5292
5293         result = string_array_from_driver_info(mem_ctx,
5294                                                driver->previous_names,
5295                                                &r->previous_names,
5296                                                NULL, NULL, 0);
5297         if (!W_ERROR_IS_OK(result)) {
5298                 return result;
5299         }
5300
5301         r->driver_date          = driver->driver_date;
5302         r->driver_version       = driver->driver_version;
5303
5304         FILL_DRIVER_STRING(mem_ctx,
5305                            driver->manufacturer_name,
5306                            r->manufacturer_name);
5307         FILL_DRIVER_STRING(mem_ctx,
5308                            driver->manufacturer_url,
5309                            r->manufacturer_url);
5310         FILL_DRIVER_STRING(mem_ctx,
5311                            driver->hardware_id,
5312                            r->hardware_id);
5313         FILL_DRIVER_STRING(mem_ctx,
5314                            driver->provider,
5315                            r->provider);
5316
5317         FILL_DRIVER_STRING(mem_ctx,
5318                            driver->print_processor,
5319                            r->print_processor);
5320         FILL_DRIVER_STRING(mem_ctx,
5321                            driver->vendor_setup,
5322                            r->vendor_setup);
5323
5324         result = string_array_from_driver_info(mem_ctx,
5325                                                driver->color_profiles,
5326                                                &r->color_profiles,
5327                                                NULL, NULL, 0);
5328         if (!W_ERROR_IS_OK(result)) {
5329                 return result;
5330         }
5331
5332         FILL_DRIVER_STRING(mem_ctx,
5333                            driver->inf_path,
5334                            r->inf_path);
5335
5336         r->printer_driver_attributes    = driver->printer_driver_attributes;
5337
5338         result = string_array_from_driver_info(mem_ctx,
5339                                                driver->core_driver_dependencies,
5340                                                &r->core_driver_dependencies,
5341                                                NULL, NULL, 0);
5342         if (!W_ERROR_IS_OK(result)) {
5343                 return result;
5344         }
5345
5346         r->min_inbox_driver_ver_date    = driver->min_inbox_driver_ver_date;
5347         r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5348
5349         return WERR_OK;
5350 }
5351
5352 #if 0 /* disabled until marshalling issues are resolved - gd */
5353 /********************************************************************
5354  ********************************************************************/
5355
5356 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5357                                           struct spoolss_DriverFileInfo *r,
5358                                           const char *cservername,
5359                                           const char *file_name,
5360                                           enum spoolss_DriverFileType file_type,
5361                                           uint32_t file_version)
5362 {
5363         r->file_name    = talloc_asprintf(mem_ctx, "\\\\%s%s",
5364                                           cservername, file_name);
5365         W_ERROR_HAVE_NO_MEMORY(r->file_name);
5366         r->file_type    = file_type;
5367         r->file_version = file_version;
5368
5369         return WERR_OK;
5370 }
5371
5372 /********************************************************************
5373  ********************************************************************/
5374
5375 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5376                                                  const struct spoolss_DriverInfo8 *driver,
5377                                                  const char *cservername,
5378                                                  struct spoolss_DriverFileInfo **info_p,
5379                                                  uint32_t *count_p)
5380 {
5381         struct spoolss_DriverFileInfo *info = NULL;
5382         uint32_t count = 0;
5383         WERROR result;
5384         uint32_t i;
5385
5386         *info_p = NULL;
5387         *count_p = 0;
5388
5389         if (strlen(driver->driver_path)) {
5390                 info = talloc_realloc(mem_ctx, info,
5391                                             struct spoolss_DriverFileInfo,
5392                                             count + 1);
5393                 W_ERROR_HAVE_NO_MEMORY(info);
5394                 result = fill_spoolss_DriverFileInfo(info,
5395                                                      &info[count],
5396                                                      cservername,
5397                                                      driver->driver_path,
5398                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5399                                                      0);
5400                 W_ERROR_NOT_OK_RETURN(result);
5401                 count++;
5402         }
5403
5404         if (strlen(driver->config_file)) {
5405                 info = talloc_realloc(mem_ctx, info,
5406                                             struct spoolss_DriverFileInfo,
5407                                             count + 1);
5408                 W_ERROR_HAVE_NO_MEMORY(info);
5409                 result = fill_spoolss_DriverFileInfo(info,
5410                                                      &info[count],
5411                                                      cservername,
5412                                                      driver->config_file,
5413                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5414                                                      0);
5415                 W_ERROR_NOT_OK_RETURN(result);
5416                 count++;
5417         }
5418
5419         if (strlen(driver->data_file)) {
5420                 info = talloc_realloc(mem_ctx, info,
5421                                             struct spoolss_DriverFileInfo,
5422                                             count + 1);
5423                 W_ERROR_HAVE_NO_MEMORY(info);
5424                 result = fill_spoolss_DriverFileInfo(info,
5425                                                      &info[count],
5426                                                      cservername,
5427                                                      driver->data_file,
5428                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
5429                                                      0);
5430                 W_ERROR_NOT_OK_RETURN(result);
5431                 count++;
5432         }
5433
5434         if (strlen(driver->help_file)) {
5435                 info = talloc_realloc(mem_ctx, info,
5436                                             struct spoolss_DriverFileInfo,
5437                                             count + 1);
5438                 W_ERROR_HAVE_NO_MEMORY(info);
5439                 result = fill_spoolss_DriverFileInfo(info,
5440                                                      &info[count],
5441                                                      cservername,
5442                                                      driver->help_file,
5443                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
5444                                                      0);
5445                 W_ERROR_NOT_OK_RETURN(result);
5446                 count++;
5447         }
5448
5449         for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5450                 info = talloc_realloc(mem_ctx, info,
5451                                             struct spoolss_DriverFileInfo,
5452                                             count + 1);
5453                 W_ERROR_HAVE_NO_MEMORY(info);
5454                 result = fill_spoolss_DriverFileInfo(info,
5455                                                      &info[count],
5456                                                      cservername,
5457                                                      driver->dependent_files[i],
5458                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5459                                                      0);
5460                 W_ERROR_NOT_OK_RETURN(result);
5461                 count++;
5462         }
5463
5464         *info_p = info;
5465         *count_p = count;
5466
5467         return WERR_OK;
5468 }
5469
5470 /********************************************************************
5471  * fill a spoolss_DriverInfo101 struct
5472  ********************************************************************/
5473
5474 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5475                                           struct spoolss_DriverInfo101 *r,
5476                                           const struct spoolss_DriverInfo8 *driver,
5477                                           const char *servername)
5478 {
5479         const char *cservername = canon_servername(servername);
5480         WERROR result;
5481
5482         r->version              = driver->version;
5483
5484         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5485         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5486         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5487         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5488
5489         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5490                                                     cservername,
5491                                                     &r->file_info,
5492                                                     &r->file_count);
5493         if (!W_ERROR_IS_OK(result)) {
5494                 return result;
5495         }
5496
5497         FILL_DRIVER_STRING(mem_ctx,
5498                            driver->monitor_name,
5499                            r->monitor_name);
5500
5501         FILL_DRIVER_STRING(mem_ctx,
5502                            driver->default_datatype,
5503                            r->default_datatype);
5504
5505         result = string_array_from_driver_info(mem_ctx,
5506                                                driver->previous_names,
5507                                                &r->previous_names,
5508                                                NULL, NULL, 0);
5509         if (!W_ERROR_IS_OK(result)) {
5510                 return result;
5511         }
5512
5513         r->driver_date          = driver->driver_date;
5514         r->driver_version       = driver->driver_version;
5515
5516         FILL_DRIVER_STRING(mem_ctx,
5517                            driver->manufacturer_name,
5518                            r->manufacturer_name);
5519         FILL_DRIVER_STRING(mem_ctx,
5520                            driver->manufacturer_url,
5521                            r->manufacturer_url);
5522         FILL_DRIVER_STRING(mem_ctx,
5523                            driver->hardware_id,
5524                            r->hardware_id);
5525         FILL_DRIVER_STRING(mem_ctx,
5526                            driver->provider,
5527                            r->provider);
5528
5529         return WERR_OK;
5530 }
5531 #endif
5532 /********************************************************************
5533  ********************************************************************/
5534
5535 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5536                                                   const struct auth_serversupplied_info *session_info,
5537                                                   struct messaging_context *msg_ctx,
5538                                                   uint32_t level,
5539                                                   union spoolss_DriverInfo *r,
5540                                                   int snum,
5541                                                   const char *servername,
5542                                                   const char *architecture,
5543                                                   uint32_t version)
5544 {
5545         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5546         struct spoolss_DriverInfo8 *driver;
5547         WERROR result;
5548         struct dcerpc_binding_handle *b;
5549
5550         if (level == 101) {
5551                 return WERR_UNKNOWN_LEVEL;
5552         }
5553
5554         result = winreg_printer_binding_handle(mem_ctx,
5555                                                session_info,
5556                                                msg_ctx,
5557                                                &b);
5558         if (!W_ERROR_IS_OK(result)) {
5559                 return result;
5560         }
5561
5562         result = winreg_get_printer(mem_ctx, b,
5563                                     lp_const_servicename(snum),
5564                                     &pinfo2);
5565
5566         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5567                 win_errstr(result)));
5568
5569         if (!W_ERROR_IS_OK(result)) {
5570                 return WERR_INVALID_PRINTER_NAME;
5571         }
5572
5573         result = winreg_get_driver(mem_ctx, b,
5574                                    architecture,
5575                                    pinfo2->drivername, version, &driver);
5576
5577         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5578                 win_errstr(result)));
5579
5580         if (!W_ERROR_IS_OK(result)) {
5581                 /*
5582                  * Is this a W2k client ?
5583                  */
5584
5585                 if (version < 3) {
5586                         talloc_free(pinfo2);
5587                         return WERR_UNKNOWN_PRINTER_DRIVER;
5588                 }
5589
5590                 /* Yes - try again with a WinNT driver. */
5591                 version = 2;
5592                 result = winreg_get_driver(mem_ctx, b,
5593                                            architecture,
5594                                            pinfo2->drivername,
5595                                            version, &driver);
5596                 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5597                         win_errstr(result)));
5598                 if (!W_ERROR_IS_OK(result)) {
5599                         talloc_free(pinfo2);
5600                         return WERR_UNKNOWN_PRINTER_DRIVER;
5601                 }
5602         }
5603
5604         switch (level) {
5605         case 1:
5606                 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5607                 break;
5608         case 2:
5609                 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5610                 break;
5611         case 3:
5612                 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5613                 break;
5614         case 4:
5615                 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5616                 break;
5617         case 5:
5618                 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5619                 break;
5620         case 6:
5621                 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5622                 break;
5623         case 8:
5624                 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5625                 break;
5626 #if 0 /* disabled until marshalling issues are resolved - gd */
5627         case 101:
5628                 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5629                 break;
5630 #endif
5631         default:
5632                 result = WERR_UNKNOWN_LEVEL;
5633                 break;
5634         }
5635
5636         talloc_free(pinfo2);
5637         talloc_free(driver);
5638
5639         return result;
5640 }
5641
5642 /****************************************************************
5643  _spoolss_GetPrinterDriver2
5644 ****************************************************************/
5645
5646 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5647                                   struct spoolss_GetPrinterDriver2 *r)
5648 {
5649         struct printer_handle *printer;
5650         WERROR result;
5651
5652         int snum;
5653
5654         /* that's an [in out] buffer */
5655
5656         if (!r->in.buffer && (r->in.offered != 0)) {
5657                 return WERR_INVALID_PARAM;
5658         }
5659
5660         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5661
5662         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5663                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5664                 return WERR_INVALID_PRINTER_NAME;
5665         }
5666
5667         *r->out.needed = 0;
5668         *r->out.server_major_version = 0;
5669         *r->out.server_minor_version = 0;
5670
5671         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5672                 return WERR_BADFID;
5673         }
5674
5675         result = construct_printer_driver_info_level(p->mem_ctx,
5676                                                      get_session_info_system(),
5677                                                      p->msg_ctx,
5678                                                      r->in.level, r->out.info,
5679                                                      snum, printer->servername,
5680                                                      r->in.architecture,
5681                                                      r->in.client_major_version);
5682         if (!W_ERROR_IS_OK(result)) {
5683                 TALLOC_FREE(r->out.info);
5684                 return result;
5685         }
5686
5687         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5688                                                r->out.info, r->in.level);
5689         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5690
5691         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5692 }
5693
5694
5695 /****************************************************************
5696  _spoolss_StartPagePrinter
5697 ****************************************************************/
5698
5699 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5700                                  struct spoolss_StartPagePrinter *r)
5701 {
5702         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5703
5704         if (!Printer) {
5705                 DEBUG(3,("_spoolss_StartPagePrinter: "
5706                         "Error in startpageprinter printer handle\n"));
5707                 return WERR_BADFID;
5708         }
5709
5710         Printer->page_started = true;
5711         return WERR_OK;
5712 }
5713
5714 /****************************************************************
5715  _spoolss_EndPagePrinter
5716 ****************************************************************/
5717
5718 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5719                                struct spoolss_EndPagePrinter *r)
5720 {
5721         int snum;
5722
5723         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5724
5725         if (!Printer) {
5726                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5727                         OUR_HANDLE(r->in.handle)));
5728                 return WERR_BADFID;
5729         }
5730
5731         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5732                 return WERR_BADFID;
5733
5734         Printer->page_started = false;
5735         print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5736
5737         return WERR_OK;
5738 }
5739
5740 /****************************************************************
5741  _spoolss_StartDocPrinter
5742 ****************************************************************/
5743
5744 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5745                                 struct spoolss_StartDocPrinter *r)
5746 {
5747         struct spoolss_DocumentInfo1 *info_1;
5748         int snum;
5749         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5750         WERROR werr;
5751         char *rhost;
5752         int rc;
5753
5754         if (!Printer) {
5755                 DEBUG(2,("_spoolss_StartDocPrinter: "
5756                         "Invalid handle (%s:%u:%u)\n",
5757                         OUR_HANDLE(r->in.handle)));
5758                 return WERR_BADFID;
5759         }
5760
5761         if (Printer->jobid) {
5762                 DEBUG(2, ("_spoolss_StartDocPrinter: "
5763                           "StartDocPrinter called twice! "
5764                           "(existing jobid = %d)\n", Printer->jobid));
5765                 return WERR_INVALID_HANDLE;
5766         }
5767
5768         if (r->in.level != 1) {
5769                 return WERR_UNKNOWN_LEVEL;
5770         }
5771
5772         info_1 = r->in.info.info1;
5773
5774         /*
5775          * a nice thing with NT is it doesn't listen to what you tell it.
5776          * when asked to send _only_ RAW datas, it tries to send datas
5777          * in EMF format.
5778          *
5779          * So I add checks like in NT Server ...
5780          */
5781
5782         if (info_1->datatype) {
5783                 if (strcmp(info_1->datatype, "RAW") != 0) {
5784                         *r->out.job_id = 0;
5785                         return WERR_INVALID_DATATYPE;
5786                 }
5787         }
5788
5789         /* get the share number of the printer */
5790         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5791                 return WERR_BADFID;
5792         }
5793
5794         rc = get_remote_hostname(p->remote_address,
5795                                  &rhost,
5796                                  p->mem_ctx);
5797         if (rc < 0) {
5798                 return WERR_NOMEM;
5799         }
5800         if (strequal(rhost,"UNKNOWN")) {
5801                 rhost = tsocket_address_inet_addr_string(p->remote_address,
5802                                                          p->mem_ctx);
5803                 if (rhost == NULL) {
5804                         return WERR_NOMEM;
5805                 }
5806         }
5807
5808         werr = print_job_start(p->session_info,
5809                                p->msg_ctx,
5810                                rhost,
5811                                snum,
5812                                info_1->document_name,
5813                                info_1->output_file,
5814                                Printer->devmode,
5815                                &Printer->jobid);
5816
5817         /* An error occured in print_job_start() so return an appropriate
5818            NT error code. */
5819
5820         if (!W_ERROR_IS_OK(werr)) {
5821                 return werr;
5822         }
5823
5824         Printer->document_started = true;
5825         *r->out.job_id = Printer->jobid;
5826
5827         return WERR_OK;
5828 }
5829
5830 /****************************************************************
5831  _spoolss_EndDocPrinter
5832 ****************************************************************/
5833
5834 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5835                               struct spoolss_EndDocPrinter *r)
5836 {
5837         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5838         NTSTATUS status;
5839         int snum;
5840
5841         if (!Printer) {
5842                 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5843                         OUR_HANDLE(r->in.handle)));
5844                 return WERR_BADFID;
5845         }
5846
5847         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5848                 return WERR_BADFID;
5849         }
5850
5851         Printer->document_started = false;
5852         status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5853         if (!NT_STATUS_IS_OK(status)) {
5854                 DEBUG(2, ("_spoolss_EndDocPrinter: "
5855                           "print_job_end failed [%s]\n",
5856                           nt_errstr(status)));
5857         }
5858
5859         Printer->jobid = 0;
5860         return ntstatus_to_werror(status);
5861 }
5862
5863 /****************************************************************
5864  _spoolss_WritePrinter
5865 ****************************************************************/
5866
5867 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5868                              struct spoolss_WritePrinter *r)
5869 {
5870         ssize_t buffer_written;
5871         int snum;
5872         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5873
5874         if (!Printer) {
5875                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5876                         OUR_HANDLE(r->in.handle)));
5877                 *r->out.num_written = r->in._data_size;
5878                 return WERR_BADFID;
5879         }
5880
5881         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5882                 return WERR_BADFID;
5883
5884         /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5885         buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5886                                                    snum, Printer->jobid,
5887                                                    (const char *)r->in.data.data,
5888                                                    (size_t)r->in._data_size);
5889         if (buffer_written == (ssize_t)-1) {
5890                 *r->out.num_written = 0;
5891                 if (errno == ENOSPC)
5892                         return WERR_NO_SPOOL_SPACE;
5893                 else
5894                         return WERR_ACCESS_DENIED;
5895         }
5896
5897         *r->out.num_written = r->in._data_size;
5898
5899         return WERR_OK;
5900 }
5901
5902 /********************************************************************
5903  * api_spoolss_getprinter
5904  * called from the spoolss dispatcher
5905  *
5906  ********************************************************************/
5907
5908 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5909                               struct pipes_struct *p)
5910 {
5911         const struct auth_serversupplied_info *session_info = p->session_info;
5912         int snum;
5913         WERROR errcode = WERR_BADFUNC;
5914         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5915
5916         if (!Printer) {
5917                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5918                         OUR_HANDLE(handle)));
5919                 return WERR_BADFID;
5920         }
5921
5922         if (!get_printer_snum(p, handle, &snum, NULL))
5923                 return WERR_BADFID;
5924
5925         switch (command) {
5926         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5927                 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
5928                 break;
5929         case SPOOLSS_PRINTER_CONTROL_RESUME:
5930         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5931                 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
5932                 break;
5933         case SPOOLSS_PRINTER_CONTROL_PURGE:
5934                 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
5935                 break;
5936         default:
5937                 return WERR_UNKNOWN_LEVEL;
5938         }
5939
5940         return errcode;
5941 }
5942
5943
5944 /****************************************************************
5945  _spoolss_AbortPrinter
5946  * From MSDN: "Deletes printer's spool file if printer is configured
5947  * for spooling"
5948 ****************************************************************/
5949
5950 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
5951                              struct spoolss_AbortPrinter *r)
5952 {
5953         struct printer_handle   *Printer = find_printer_index_by_hnd(p, r->in.handle);
5954         int             snum;
5955         WERROR          errcode = WERR_OK;
5956
5957         if (!Printer) {
5958                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5959                         OUR_HANDLE(r->in.handle)));
5960                 return WERR_BADFID;
5961         }
5962
5963         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5964                 return WERR_BADFID;
5965
5966         if (!Printer->document_started) {
5967                 return WERR_SPL_NO_STARTDOC;
5968         }
5969
5970         errcode = print_job_delete(p->session_info,
5971                                    p->msg_ctx,
5972                                    snum,
5973                                    Printer->jobid);
5974
5975         return errcode;
5976 }
5977
5978 /********************************************************************
5979  * called by spoolss_api_setprinter
5980  * when updating a printer description
5981  ********************************************************************/
5982
5983 static WERROR update_printer_sec(struct policy_handle *handle,
5984                                  struct pipes_struct *p,
5985                                  struct sec_desc_buf *secdesc_ctr)
5986 {
5987         struct spoolss_security_descriptor *new_secdesc = NULL;
5988         struct spoolss_security_descriptor *old_secdesc = NULL;
5989         const char *printer;
5990         WERROR result;
5991         int snum;
5992         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5993         struct dcerpc_binding_handle *b;
5994
5995         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5996                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5997                          OUR_HANDLE(handle)));
5998
5999                 result = WERR_BADFID;
6000                 goto done;
6001         }
6002
6003         if (secdesc_ctr == NULL) {
6004                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
6005                 result = WERR_INVALID_PARAM;
6006                 goto done;
6007         }
6008         printer = lp_const_servicename(snum);
6009
6010         /* Check the user has permissions to change the security
6011            descriptor.  By experimentation with two NT machines, the user
6012            requires Full Access to the printer to change security
6013            information. */
6014
6015         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
6016                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
6017                 result = WERR_ACCESS_DENIED;
6018                 goto done;
6019         }
6020
6021         result = winreg_printer_binding_handle(p->mem_ctx,
6022                                                get_session_info_system(),
6023                                                p->msg_ctx,
6024                                                &b);
6025         if (!W_ERROR_IS_OK(result)) {
6026                 goto done;
6027         }
6028
6029         /* NT seems to like setting the security descriptor even though
6030            nothing may have actually changed. */
6031         result = winreg_get_printer_secdesc(p->mem_ctx, b,
6032                                             printer,
6033                                             &old_secdesc);
6034         if (!W_ERROR_IS_OK(result)) {
6035                 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
6036                 result = WERR_BADFID;
6037                 goto done;
6038         }
6039
6040         if (DEBUGLEVEL >= 10) {
6041                 struct security_acl *the_acl;
6042                 int i;
6043
6044                 the_acl = old_secdesc->dacl;
6045                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6046                            printer, the_acl->num_aces));
6047
6048                 for (i = 0; i < the_acl->num_aces; i++) {
6049                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6050                                            &the_acl->aces[i].trustee),
6051                                   the_acl->aces[i].access_mask));
6052                 }
6053
6054                 the_acl = secdesc_ctr->sd->dacl;
6055
6056                 if (the_acl) {
6057                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6058                                    printer, the_acl->num_aces));
6059
6060                         for (i = 0; i < the_acl->num_aces; i++) {
6061                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6062                                                    &the_acl->aces[i].trustee),
6063                                            the_acl->aces[i].access_mask));
6064                         }
6065                 } else {
6066                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6067                 }
6068         }
6069
6070         new_secdesc = sec_desc_merge(p->mem_ctx, secdesc_ctr->sd, old_secdesc);
6071         if (new_secdesc == NULL) {
6072                 result = WERR_NOMEM;
6073                 goto done;
6074         }
6075
6076         if (security_descriptor_equal(new_secdesc, old_secdesc)) {
6077                 result = WERR_OK;
6078                 goto done;
6079         }
6080
6081         result = winreg_set_printer_secdesc(p->mem_ctx, b,
6082                                             printer,
6083                                             new_secdesc);
6084
6085  done:
6086         return result;
6087 }
6088
6089 /********************************************************************
6090  Canonicalize printer info from a client
6091  ********************************************************************/
6092
6093 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
6094                              struct spoolss_SetPrinterInfo2 *info2,
6095                              int snum)
6096 {
6097         fstring printername;
6098         const char *p;
6099
6100         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6101                 "portname=%s drivername=%s comment=%s location=%s\n",
6102                 info2->servername, info2->printername, info2->sharename,
6103                 info2->portname, info2->drivername, info2->comment,
6104                 info2->location));
6105
6106         /* we force some elements to "correct" values */
6107         info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
6108         if (info2->servername == NULL) {
6109                 return false;
6110         }
6111         info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6112         if (info2->sharename == NULL) {
6113                 return false;
6114         }
6115
6116         /* check to see if we allow printername != sharename */
6117         if (lp_force_printername(snum)) {
6118                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6119                                         lp_netbios_name(), info2->sharename);
6120         } else {
6121                 /* make sure printername is in \\server\printername format */
6122                 fstrcpy(printername, info2->printername);
6123                 p = printername;
6124                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6125                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6126                                 p++;
6127                 }
6128
6129                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6130                                         lp_netbios_name(), p);
6131         }
6132         if (info2->printername == NULL) {
6133                 return false;
6134         }
6135
6136         info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6137         info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6138
6139         return true;
6140 }
6141
6142 /****************************************************************************
6143 ****************************************************************************/
6144
6145 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6146 {
6147         char *cmd = lp_addport_cmd();
6148         char *command = NULL;
6149         int ret;
6150         bool is_print_op = false;
6151
6152         if ( !*cmd ) {
6153                 return WERR_ACCESS_DENIED;
6154         }
6155
6156         command = talloc_asprintf(ctx,
6157                         "%s \"%s\" \"%s\"", cmd, portname, uri );
6158         if (!command) {
6159                 return WERR_NOMEM;
6160         }
6161
6162         if ( token )
6163                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6164
6165         DEBUG(10,("Running [%s]\n", command));
6166
6167         /********* BEGIN SePrintOperatorPrivilege **********/
6168
6169         if ( is_print_op )
6170                 become_root();
6171
6172         ret = smbrun(command, NULL);
6173
6174         if ( is_print_op )
6175                 unbecome_root();
6176
6177         /********* END SePrintOperatorPrivilege **********/
6178
6179         DEBUGADD(10,("returned [%d]\n", ret));
6180
6181         TALLOC_FREE(command);
6182
6183         if ( ret != 0 ) {
6184                 return WERR_ACCESS_DENIED;
6185         }
6186
6187         return WERR_OK;
6188 }
6189
6190 /****************************************************************************
6191 ****************************************************************************/
6192
6193 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6194                              struct spoolss_SetPrinterInfo2 *info2,
6195                              const char *remote_machine,
6196                              struct messaging_context *msg_ctx)
6197 {
6198         char *cmd = lp_addprinter_cmd();
6199         char **qlines;
6200         char *command = NULL;
6201         int numlines;
6202         int ret;
6203         int fd;
6204         bool is_print_op = false;
6205
6206         if (!remote_machine) {
6207                 return false;
6208         }
6209
6210         command = talloc_asprintf(ctx,
6211                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6212                         cmd, info2->printername, info2->sharename,
6213                         info2->portname, info2->drivername,
6214                         info2->location, info2->comment, remote_machine);
6215         if (!command) {
6216                 return false;
6217         }
6218
6219         if ( token )
6220                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6221
6222         DEBUG(10,("Running [%s]\n", command));
6223
6224         /********* BEGIN SePrintOperatorPrivilege **********/
6225
6226         if ( is_print_op )
6227                 become_root();
6228
6229         if ( (ret = smbrun(command, &fd)) == 0 ) {
6230                 /* Tell everyone we updated smb.conf. */
6231                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6232         }
6233
6234         if ( is_print_op )
6235                 unbecome_root();
6236
6237         /********* END SePrintOperatorPrivilege **********/
6238
6239         DEBUGADD(10,("returned [%d]\n", ret));
6240
6241         TALLOC_FREE(command);
6242
6243         if ( ret != 0 ) {
6244                 if (fd != -1)
6245                         close(fd);
6246                 return false;
6247         }
6248
6249         /* reload our services immediately */
6250         become_root();
6251         reload_services(msg_ctx, -1, false);
6252         unbecome_root();
6253
6254         numlines = 0;
6255         /* Get lines and convert them back to dos-codepage */
6256         qlines = fd_lines_load(fd, &numlines, 0, NULL);
6257         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6258         close(fd);
6259
6260         /* Set the portname to what the script says the portname should be. */
6261         /* but don't require anything to be return from the script exit a good error code */
6262
6263         if (numlines) {
6264                 /* Set the portname to what the script says the portname should be. */
6265                 info2->portname = talloc_strdup(ctx, qlines[0]);
6266                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6267         }
6268
6269         TALLOC_FREE(qlines);
6270         return true;
6271 }
6272
6273 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6274                                const struct auth_serversupplied_info *session_info,
6275                                struct messaging_context *msg_ctx,
6276                                int snum,
6277                                struct spoolss_SetPrinterInfo2 *printer,
6278                                struct spoolss_PrinterInfo2 *old_printer)
6279 {
6280         bool force_update = (old_printer == NULL);
6281         const char *dnsdomname;
6282         const char *longname;
6283         const char *uncname;
6284         const char *spooling;
6285         DATA_BLOB buffer;
6286         WERROR result = WERR_OK;
6287         struct dcerpc_binding_handle *b;
6288
6289         result = winreg_printer_binding_handle(mem_ctx,
6290                                                session_info,
6291                                                msg_ctx,
6292                                                &b);
6293         if (!W_ERROR_IS_OK(result)) {
6294                 return result;
6295         }
6296
6297         if (force_update || !strequal(printer->drivername, old_printer->drivername)) {
6298                 push_reg_sz(mem_ctx, &buffer, printer->drivername);
6299                 winreg_set_printer_dataex(mem_ctx, b,
6300                                           printer->sharename,
6301                                           SPOOL_DSSPOOLER_KEY,
6302                                           SPOOL_REG_DRIVERNAME,
6303                                           REG_SZ,
6304                                           buffer.data,
6305                                           buffer.length);
6306
6307                 if (!force_update) {
6308                         DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6309                                 printer->drivername));
6310
6311                         notify_printer_driver(server_event_context(), msg_ctx,
6312                                               snum, printer->drivername ?
6313                                               printer->drivername : "");
6314                 }
6315         }
6316
6317         if (force_update || !strequal(printer->comment, old_printer->comment)) {
6318                 push_reg_sz(mem_ctx, &buffer, printer->comment);
6319                 winreg_set_printer_dataex(mem_ctx, b,
6320                                           printer->sharename,
6321                                           SPOOL_DSSPOOLER_KEY,
6322                                           SPOOL_REG_DESCRIPTION,
6323                                           REG_SZ,
6324                                           buffer.data,
6325                                           buffer.length);
6326
6327                 if (!force_update) {
6328                         notify_printer_comment(server_event_context(), msg_ctx,
6329                                                snum, printer->comment ?
6330                                                printer->comment : "");
6331                 }
6332         }
6333
6334         if (force_update || !strequal(printer->sharename, old_printer->sharename)) {
6335                 push_reg_sz(mem_ctx, &buffer, printer->sharename);
6336                 winreg_set_printer_dataex(mem_ctx, b,
6337                                           printer->sharename,
6338                                           SPOOL_DSSPOOLER_KEY,
6339                                           SPOOL_REG_PRINTSHARENAME,
6340                                           REG_SZ,
6341                                           buffer.data,
6342                                           buffer.length);
6343
6344                 if (!force_update) {
6345                         notify_printer_sharename(server_event_context(),
6346                                                  msg_ctx,
6347                                                  snum, printer->sharename ?
6348                                                  printer->sharename : "");
6349                 }
6350         }
6351
6352         if (force_update || !strequal(printer->printername, old_printer->printername)) {
6353                 const char *p;
6354
6355                 p = strrchr(printer->printername, '\\' );
6356                 if (p != NULL) {
6357                         p++;
6358                 } else {
6359                         p = printer->printername;
6360                 }
6361
6362                 push_reg_sz(mem_ctx, &buffer, p);
6363                 winreg_set_printer_dataex(mem_ctx, b,
6364                                           printer->sharename,
6365                                           SPOOL_DSSPOOLER_KEY,
6366                                           SPOOL_REG_PRINTERNAME,
6367                                           REG_SZ,
6368                                           buffer.data,
6369                                           buffer.length);
6370
6371                 if (!force_update) {
6372                         notify_printer_printername(server_event_context(),
6373                                                    msg_ctx, snum, p ? p : "");
6374                 }
6375         }
6376
6377         if (force_update || !strequal(printer->portname, old_printer->portname)) {
6378                 push_reg_sz(mem_ctx, &buffer, printer->portname);
6379                 winreg_set_printer_dataex(mem_ctx, b,
6380                                           printer->sharename,
6381                                           SPOOL_DSSPOOLER_KEY,
6382                                           SPOOL_REG_PORTNAME,
6383                                           REG_SZ,
6384                                           buffer.data,
6385                                           buffer.length);
6386
6387                 if (!force_update) {
6388                         notify_printer_port(server_event_context(),
6389                                             msg_ctx, snum, printer->portname ?
6390                                             printer->portname : "");
6391                 }
6392         }
6393
6394         if (force_update || !strequal(printer->location, old_printer->location)) {
6395                 push_reg_sz(mem_ctx, &buffer, printer->location);
6396                 winreg_set_printer_dataex(mem_ctx, b,
6397                                           printer->sharename,
6398                                           SPOOL_DSSPOOLER_KEY,
6399                                           SPOOL_REG_LOCATION,
6400                                           REG_SZ,
6401                                           buffer.data,
6402                                           buffer.length);
6403
6404                 if (!force_update) {
6405                         notify_printer_location(server_event_context(),
6406                                                 msg_ctx, snum,
6407                                                 printer->location ?
6408                                                 printer->location : "");
6409                 }
6410         }
6411
6412         if (force_update || !strequal(printer->sepfile, old_printer->sepfile)) {
6413                 push_reg_sz(mem_ctx, &buffer, printer->sepfile);
6414                 winreg_set_printer_dataex(mem_ctx, b,
6415                                           printer->sharename,
6416                                           SPOOL_DSSPOOLER_KEY,
6417                                           SPOOL_REG_PRINTSEPARATORFILE,
6418                                           REG_SZ,
6419                                           buffer.data,
6420                                           buffer.length);
6421
6422                 if (!force_update) {
6423                         notify_printer_sepfile(server_event_context(),
6424                                                msg_ctx, snum,
6425                                                printer->sepfile ?
6426                                                printer->sepfile : "");
6427                 }
6428         }
6429
6430         if (force_update || printer->starttime != old_printer->starttime) {
6431                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6432                 SIVAL(buffer.data, 0, printer->starttime);
6433                 winreg_set_printer_dataex(mem_ctx, b,
6434                                           printer->sharename,
6435                                           SPOOL_DSSPOOLER_KEY,
6436                                           SPOOL_REG_PRINTSTARTTIME,
6437                                           REG_DWORD,
6438                                           buffer.data,
6439                                           buffer.length);
6440         }
6441
6442         if (force_update || printer->untiltime != old_printer->untiltime) {
6443                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6444                 SIVAL(buffer.data, 0, printer->untiltime);
6445                 winreg_set_printer_dataex(mem_ctx, b,
6446                                           printer->sharename,
6447                                           SPOOL_DSSPOOLER_KEY,
6448                                           SPOOL_REG_PRINTENDTIME,
6449                                           REG_DWORD,
6450                                           buffer.data,
6451                                           buffer.length);
6452         }
6453
6454         if (force_update || printer->priority != old_printer->priority) {
6455                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6456                 SIVAL(buffer.data, 0, printer->priority);
6457                 winreg_set_printer_dataex(mem_ctx, b,
6458                                           printer->sharename,
6459                                           SPOOL_DSSPOOLER_KEY,
6460                                           SPOOL_REG_PRIORITY,
6461                                           REG_DWORD,
6462                                           buffer.data,
6463                                           buffer.length);
6464         }
6465
6466         if (force_update || printer->attributes != old_printer->attributes) {
6467                 buffer = data_blob_talloc(mem_ctx, NULL, 4);
6468                 SIVAL(buffer.data, 0, (printer->attributes &
6469                                        PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6470                 winreg_set_printer_dataex(mem_ctx, b,
6471                                           printer->sharename,
6472                                           SPOOL_DSSPOOLER_KEY,
6473                                           SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6474                                           REG_DWORD,
6475                                           buffer.data,
6476                                           buffer.length);
6477
6478                 switch (printer->attributes & 0x3) {
6479                         case 0:
6480                                 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6481                                 break;
6482                         case 1:
6483                                 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6484                                 break;
6485                         case 2:
6486                                 spooling = SPOOL_REGVAL_PRINTDIRECT;
6487                                 break;
6488                         default:
6489                                 spooling = "unknown";
6490                 }
6491                 push_reg_sz(mem_ctx, &buffer, spooling);
6492                 winreg_set_printer_dataex(mem_ctx, b,
6493                                           printer->sharename,
6494                                           SPOOL_DSSPOOLER_KEY,
6495                                           SPOOL_REG_PRINTSPOOLING,
6496                                           REG_SZ,
6497                                           buffer.data,
6498                                           buffer.length);
6499         }
6500
6501         push_reg_sz(mem_ctx, &buffer, lp_netbios_name());
6502         winreg_set_printer_dataex(mem_ctx, b,
6503                                   printer->sharename,
6504                                   SPOOL_DSSPOOLER_KEY,
6505                                   SPOOL_REG_SHORTSERVERNAME,
6506                                   REG_SZ,
6507                                   buffer.data,
6508                                   buffer.length);
6509
6510         dnsdomname = get_mydnsfullname();
6511         if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6512                 longname = talloc_strdup(mem_ctx, dnsdomname);
6513         } else {
6514                 longname = talloc_strdup(mem_ctx, lp_netbios_name());
6515         }
6516         if (longname == NULL) {
6517                 result = WERR_NOMEM;
6518                 goto done;
6519         }
6520
6521         push_reg_sz(mem_ctx, &buffer, longname);
6522         winreg_set_printer_dataex(mem_ctx, b,
6523                                   printer->sharename,
6524                                   SPOOL_DSSPOOLER_KEY,
6525                                   SPOOL_REG_SERVERNAME,
6526                                   REG_SZ,
6527                                   buffer.data,
6528                                   buffer.length);
6529
6530         uncname = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6531                                   lp_netbios_name(), printer->sharename);
6532         push_reg_sz(mem_ctx, &buffer, uncname);
6533         winreg_set_printer_dataex(mem_ctx, b,
6534                                   printer->sharename,
6535                                   SPOOL_DSSPOOLER_KEY,
6536                                   SPOOL_REG_UNCNAME,
6537                                   REG_SZ,
6538                                   buffer.data,
6539                                   buffer.length);
6540
6541 done:
6542         return result;
6543 }
6544
6545 /********************************************************************
6546  * Called by spoolss_api_setprinter
6547  * when updating a printer description.
6548  ********************************************************************/
6549
6550 static WERROR update_printer(struct pipes_struct *p,
6551                              struct policy_handle *handle,
6552                              struct spoolss_SetPrinterInfoCtr *info_ctr,
6553                              struct spoolss_DeviceMode *devmode)
6554 {
6555         uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6556         struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6557         struct spoolss_PrinterInfo2 *old_printer;
6558         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6559         int snum;
6560         WERROR result = WERR_OK;
6561         TALLOC_CTX *tmp_ctx;
6562         struct dcerpc_binding_handle *b;
6563
6564         DEBUG(8,("update_printer\n"));
6565
6566         tmp_ctx = talloc_new(p->mem_ctx);
6567         if (tmp_ctx == NULL) {
6568                 return WERR_NOMEM;
6569         }
6570
6571         if (!Printer) {
6572                 result = WERR_BADFID;
6573                 goto done;
6574         }
6575
6576         if (!get_printer_snum(p, handle, &snum, NULL)) {
6577                 result = WERR_BADFID;
6578                 goto done;
6579         }
6580
6581         result = winreg_printer_binding_handle(tmp_ctx,
6582                                                get_session_info_system(),
6583                                                p->msg_ctx,
6584                                                &b);
6585         if (!W_ERROR_IS_OK(result)) {
6586                 goto done;
6587         }
6588
6589         result = winreg_get_printer(tmp_ctx, b,
6590                                     lp_const_servicename(snum),
6591                                     &old_printer);
6592         if (!W_ERROR_IS_OK(result)) {
6593                 result = WERR_BADFID;
6594                 goto done;
6595         }
6596
6597         /* Do sanity check on the requested changes for Samba */
6598         if (!check_printer_ok(tmp_ctx, printer, snum)) {
6599                 result = WERR_INVALID_PARAM;
6600                 goto done;
6601         }
6602
6603         /* FIXME!!! If the driver has changed we really should verify that
6604            it is installed before doing much else   --jerry */
6605
6606         /* Check calling user has permission to update printer description */
6607         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6608                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6609                 result = WERR_ACCESS_DENIED;
6610                 goto done;
6611         }
6612
6613         /* Call addprinter hook */
6614         /* Check changes to see if this is really needed */
6615
6616         if (*lp_addprinter_cmd() &&
6617                         (!strequal(printer->drivername, old_printer->drivername) ||
6618                          !strequal(printer->comment, old_printer->comment) ||
6619                          !strequal(printer->portname, old_printer->portname) ||
6620                          !strequal(printer->location, old_printer->location)) )
6621         {
6622                 char *raddr;
6623
6624                 raddr = tsocket_address_inet_addr_string(p->remote_address,
6625                                                          p->mem_ctx);
6626                 if (raddr == NULL) {
6627                         return WERR_NOMEM;
6628                 }
6629
6630                 /* add_printer_hook() will call reload_services() */
6631                 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6632                                       printer, raddr,
6633                                       p->msg_ctx)) {
6634                         result = WERR_ACCESS_DENIED;
6635                         goto done;
6636                 }
6637         }
6638
6639         update_dsspooler(tmp_ctx,
6640                          get_session_info_system(),
6641                          p->msg_ctx,
6642                          snum,
6643                          printer,
6644                          old_printer);
6645
6646         printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6647
6648         if (devmode == NULL) {
6649                 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6650         }
6651         result = winreg_update_printer(tmp_ctx, b,
6652                                        printer->sharename,
6653                                        printer_mask,
6654                                        printer,
6655                                        devmode,
6656                                        NULL);
6657
6658 done:
6659         talloc_free(tmp_ctx);
6660
6661         return result;
6662 }
6663
6664 /****************************************************************************
6665 ****************************************************************************/
6666 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6667                                            struct policy_handle *handle,
6668                                            struct spoolss_SetPrinterInfo7 *info7)
6669 {
6670 #ifdef HAVE_ADS
6671         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6672         WERROR result;
6673         int snum;
6674         struct printer_handle *Printer;
6675
6676         if ( lp_security() != SEC_ADS ) {
6677                 return WERR_UNKNOWN_LEVEL;
6678         }
6679
6680         Printer = find_printer_index_by_hnd(p, handle);
6681
6682         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6683
6684         if (!Printer)
6685                 return WERR_BADFID;
6686
6687         if (!get_printer_snum(p, handle, &snum, NULL))
6688                 return WERR_BADFID;
6689
6690         result = winreg_get_printer_internal(p->mem_ctx,
6691                                     get_session_info_system(),
6692                                     p->msg_ctx,
6693                                     lp_servicename(snum),
6694                                     &pinfo2);
6695         if (!W_ERROR_IS_OK(result)) {
6696                 return WERR_BADFID;
6697         }
6698
6699         nt_printer_publish(pinfo2,
6700                            get_session_info_system(),
6701                            p->msg_ctx,
6702                            pinfo2,
6703                            info7->action);
6704
6705         TALLOC_FREE(pinfo2);
6706         return WERR_OK;
6707 #else
6708         return WERR_UNKNOWN_LEVEL;
6709 #endif
6710 }
6711
6712 /********************************************************************
6713  ********************************************************************/
6714
6715 static WERROR update_printer_devmode(struct pipes_struct *p,
6716                                      struct policy_handle *handle,
6717                                      struct spoolss_DeviceMode *devmode)
6718 {
6719         int snum;
6720         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6721         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6722
6723         DEBUG(8,("update_printer_devmode\n"));
6724
6725         if (!Printer) {
6726                 return WERR_BADFID;
6727         }
6728
6729         if (!get_printer_snum(p, handle, &snum, NULL)) {
6730                 return WERR_BADFID;
6731         }
6732
6733         /* Check calling user has permission to update printer description */
6734         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6735                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6736                 return WERR_ACCESS_DENIED;
6737         }
6738
6739         return winreg_update_printer_internal(p->mem_ctx,
6740                                      get_session_info_system(),
6741                                      p->msg_ctx,
6742                                      lp_const_servicename(snum),
6743                                      info2_mask,
6744                                      NULL,
6745                                      devmode,
6746                                      NULL);
6747 }
6748
6749
6750 /****************************************************************
6751  _spoolss_SetPrinter
6752 ****************************************************************/
6753
6754 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6755                            struct spoolss_SetPrinter *r)
6756 {
6757         WERROR result;
6758
6759         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6760
6761         if (!Printer) {
6762                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6763                         OUR_HANDLE(r->in.handle)));
6764                 return WERR_BADFID;
6765         }
6766
6767         /* check the level */
6768         switch (r->in.info_ctr->level) {
6769                 case 0:
6770                         return control_printer(r->in.handle, r->in.command, p);
6771                 case 2:
6772                         result = update_printer(p, r->in.handle,
6773                                                 r->in.info_ctr,
6774                                                 r->in.devmode_ctr->devmode);
6775                         if (!W_ERROR_IS_OK(result))
6776                                 return result;
6777                         if (r->in.secdesc_ctr->sd)
6778                                 result = update_printer_sec(r->in.handle, p,
6779                                                             r->in.secdesc_ctr);
6780                         return result;
6781                 case 3:
6782                         return update_printer_sec(r->in.handle, p,
6783                                                   r->in.secdesc_ctr);
6784                 case 7:
6785                         return publish_or_unpublish_printer(p, r->in.handle,
6786                                                             r->in.info_ctr->info.info7);
6787                 case 8:
6788                         return update_printer_devmode(p, r->in.handle,
6789                                                       r->in.devmode_ctr->devmode);
6790                 default:
6791                         return WERR_UNKNOWN_LEVEL;
6792         }
6793 }
6794
6795 /****************************************************************
6796  _spoolss_FindClosePrinterNotify
6797 ****************************************************************/
6798
6799 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
6800                                        struct spoolss_FindClosePrinterNotify *r)
6801 {
6802         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6803
6804         if (!Printer) {
6805                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6806                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6807                 return WERR_BADFID;
6808         }
6809
6810         if (Printer->notify.cli_chan != NULL &&
6811             Printer->notify.cli_chan->active_connections > 0) {
6812                 int snum = -1;
6813
6814                 if (Printer->printer_type == SPLHND_PRINTER) {
6815                         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6816                                 return WERR_BADFID;
6817                         }
6818                 }
6819
6820                 srv_spoolss_replycloseprinter(snum, Printer);
6821         }
6822
6823         Printer->notify.flags=0;
6824         Printer->notify.options=0;
6825         Printer->notify.localmachine[0]='\0';
6826         Printer->notify.printerlocal=0;
6827         TALLOC_FREE(Printer->notify.option);
6828
6829         return WERR_OK;
6830 }
6831
6832 /****************************************************************
6833  _spoolss_AddJob
6834 ****************************************************************/
6835
6836 WERROR _spoolss_AddJob(struct pipes_struct *p,
6837                        struct spoolss_AddJob *r)
6838 {
6839         if (!r->in.buffer && (r->in.offered != 0)) {
6840                 return WERR_INVALID_PARAM;
6841         }
6842
6843         /* this is what a NT server returns for AddJob. AddJob must fail on
6844          * non-local printers */
6845
6846         if (r->in.level != 1) {
6847                 return WERR_UNKNOWN_LEVEL;
6848         }
6849
6850         return WERR_INVALID_PARAM;
6851 }
6852
6853 /****************************************************************************
6854 fill_job_info1
6855 ****************************************************************************/
6856
6857 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6858                              struct spoolss_JobInfo1 *r,
6859                              const print_queue_struct *queue,
6860                              int position, int snum,
6861                              struct spoolss_PrinterInfo2 *pinfo2)
6862 {
6863         struct tm *t;
6864
6865         t = gmtime(&queue->time);
6866
6867         r->job_id               = queue->job;
6868
6869         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6870         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6871         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
6872         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6873         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6874         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6875         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6876         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6877         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6878         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6879         r->text_status          = talloc_strdup(mem_ctx, "");
6880         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6881
6882         r->status               = nt_printj_status(queue->status);
6883         r->priority             = queue->priority;
6884         r->position             = position;
6885         r->total_pages          = queue->page_count;
6886         r->pages_printed        = 0; /* ??? */
6887
6888         init_systemtime(&r->submitted, t);
6889
6890         return WERR_OK;
6891 }
6892
6893 /****************************************************************************
6894 fill_job_info2
6895 ****************************************************************************/
6896
6897 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6898                              struct spoolss_JobInfo2 *r,
6899                              const print_queue_struct *queue,
6900                              int position, int snum,
6901                              struct spoolss_PrinterInfo2 *pinfo2,
6902                              struct spoolss_DeviceMode *devmode)
6903 {
6904         struct tm *t;
6905
6906         t = gmtime(&queue->time);
6907
6908         r->job_id               = queue->job;
6909
6910         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6911         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6912         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
6913         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6914         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6915         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6916         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6917         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6918         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
6919         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6920         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6921         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6922         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
6923         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6924         r->parameters           = talloc_strdup(mem_ctx, "");
6925         W_ERROR_HAVE_NO_MEMORY(r->parameters);
6926         r->driver_name          = talloc_strdup(mem_ctx, pinfo2->drivername);
6927         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6928
6929         r->devmode              = devmode;
6930
6931         r->text_status          = talloc_strdup(mem_ctx, "");
6932         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6933
6934         r->secdesc              = NULL;
6935
6936         r->status               = nt_printj_status(queue->status);
6937         r->priority             = queue->priority;
6938         r->position             = position;
6939         r->start_time           = 0;
6940         r->until_time           = 0;
6941         r->total_pages          = queue->page_count;
6942         r->size                 = queue->size;
6943         init_systemtime(&r->submitted, t);
6944         r->time                 = 0;
6945         r->pages_printed        = 0; /* ??? */
6946
6947         return WERR_OK;
6948 }
6949
6950 /****************************************************************************
6951 fill_job_info3
6952 ****************************************************************************/
6953
6954 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6955                              struct spoolss_JobInfo3 *r,
6956                              const print_queue_struct *queue,
6957                              const print_queue_struct *next_queue,
6958                              int position, int snum,
6959                              struct spoolss_PrinterInfo2 *pinfo2)
6960 {
6961         r->job_id               = queue->job;
6962         r->next_job_id          = 0;
6963         if (next_queue) {
6964                 r->next_job_id  = next_queue->job;
6965         }
6966         r->reserved             = 0;
6967
6968         return WERR_OK;
6969 }
6970
6971 /****************************************************************************
6972  Enumjobs at level 1.
6973 ****************************************************************************/
6974
6975 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6976                               const print_queue_struct *queue,
6977                               uint32_t num_queues, int snum,
6978                               struct spoolss_PrinterInfo2 *pinfo2,
6979                               union spoolss_JobInfo **info_p,
6980                               uint32_t *count)
6981 {
6982         union spoolss_JobInfo *info;
6983         int i;
6984         WERROR result = WERR_OK;
6985
6986         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
6987         W_ERROR_HAVE_NO_MEMORY(info);
6988
6989         *count = num_queues;
6990
6991         for (i=0; i<*count; i++) {
6992                 result = fill_job_info1(info,
6993                                         &info[i].info1,
6994                                         &queue[i],
6995                                         i,
6996                                         snum,
6997                                         pinfo2);
6998                 if (!W_ERROR_IS_OK(result)) {
6999                         goto out;
7000                 }
7001         }
7002
7003  out:
7004         if (!W_ERROR_IS_OK(result)) {
7005                 TALLOC_FREE(info);
7006                 *count = 0;
7007                 return result;
7008         }
7009
7010         *info_p = info;
7011
7012         return WERR_OK;
7013 }
7014
7015 /****************************************************************************
7016  Enumjobs at level 2.
7017 ****************************************************************************/
7018
7019 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
7020                               const print_queue_struct *queue,
7021                               uint32_t num_queues, int snum,
7022                               struct spoolss_PrinterInfo2 *pinfo2,
7023                               union spoolss_JobInfo **info_p,
7024                               uint32_t *count)
7025 {
7026         union spoolss_JobInfo *info;
7027         int i;
7028         WERROR result = WERR_OK;
7029
7030         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7031         W_ERROR_HAVE_NO_MEMORY(info);
7032
7033         *count = num_queues;
7034
7035         for (i=0; i<*count; i++) {
7036                 struct spoolss_DeviceMode *devmode;
7037
7038                 result = spoolss_create_default_devmode(info,
7039                                                         pinfo2->printername,
7040                                                         &devmode);
7041                 if (!W_ERROR_IS_OK(result)) {
7042                         DEBUG(3, ("Can't proceed w/o a devmode!"));
7043                         goto out;
7044                 }
7045
7046                 result = fill_job_info2(info,
7047                                         &info[i].info2,
7048                                         &queue[i],
7049                                         i,
7050                                         snum,
7051                                         pinfo2,
7052                                         devmode);
7053                 if (!W_ERROR_IS_OK(result)) {
7054                         goto out;
7055                 }
7056         }
7057
7058  out:
7059         if (!W_ERROR_IS_OK(result)) {
7060                 TALLOC_FREE(info);
7061                 *count = 0;
7062                 return result;
7063         }
7064
7065         *info_p = info;
7066
7067         return WERR_OK;
7068 }
7069
7070 /****************************************************************************
7071  Enumjobs at level 3.
7072 ****************************************************************************/
7073
7074 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
7075                               const print_queue_struct *queue,
7076                               uint32_t num_queues, int snum,
7077                               struct spoolss_PrinterInfo2 *pinfo2,
7078                               union spoolss_JobInfo **info_p,
7079                               uint32_t *count)
7080 {
7081         union spoolss_JobInfo *info;
7082         int i;
7083         WERROR result = WERR_OK;
7084
7085         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7086         W_ERROR_HAVE_NO_MEMORY(info);
7087
7088         *count = num_queues;
7089
7090         for (i=0; i<*count; i++) {
7091                 const print_queue_struct *next_queue = NULL;
7092
7093                 if (i+1 < *count) {
7094                         next_queue = &queue[i+1];
7095                 }
7096
7097                 result = fill_job_info3(info,
7098                                         &info[i].info3,
7099                                         &queue[i],
7100                                         next_queue,
7101                                         i,
7102                                         snum,
7103                                         pinfo2);
7104                 if (!W_ERROR_IS_OK(result)) {
7105                         goto out;
7106                 }
7107         }
7108
7109  out:
7110         if (!W_ERROR_IS_OK(result)) {
7111                 TALLOC_FREE(info);
7112                 *count = 0;
7113                 return result;
7114         }
7115
7116         *info_p = info;
7117
7118         return WERR_OK;
7119 }
7120
7121 /****************************************************************
7122  _spoolss_EnumJobs
7123 ****************************************************************/
7124
7125 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7126                          struct spoolss_EnumJobs *r)
7127 {
7128         WERROR result;
7129         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7130         int snum;
7131         print_status_struct prt_status;
7132         print_queue_struct *queue = NULL;
7133         uint32_t count;
7134
7135         /* that's an [in out] buffer */
7136
7137         if (!r->in.buffer && (r->in.offered != 0)) {
7138                 return WERR_INVALID_PARAM;
7139         }
7140
7141         DEBUG(4,("_spoolss_EnumJobs\n"));
7142
7143         *r->out.needed = 0;
7144         *r->out.count = 0;
7145         *r->out.info = NULL;
7146
7147         /* lookup the printer snum and tdb entry */
7148
7149         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7150                 return WERR_BADFID;
7151         }
7152
7153         result = winreg_get_printer_internal(p->mem_ctx,
7154                                     get_session_info_system(),
7155                                     p->msg_ctx,
7156                                     lp_const_servicename(snum),
7157                                     &pinfo2);
7158         if (!W_ERROR_IS_OK(result)) {
7159                 return result;
7160         }
7161
7162         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7163         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7164                 count, prt_status.status, prt_status.message));
7165
7166         if (count == 0) {
7167                 SAFE_FREE(queue);
7168                 TALLOC_FREE(pinfo2);
7169                 return WERR_OK;
7170         }
7171
7172         switch (r->in.level) {
7173         case 1:
7174                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7175                                          pinfo2, r->out.info, r->out.count);
7176                 break;
7177         case 2:
7178                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7179                                          pinfo2, r->out.info, r->out.count);
7180                 break;
7181         case 3:
7182                 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7183                                          pinfo2, r->out.info, r->out.count);
7184                 break;
7185         default:
7186                 result = WERR_UNKNOWN_LEVEL;
7187                 break;
7188         }
7189
7190         SAFE_FREE(queue);
7191         TALLOC_FREE(pinfo2);
7192
7193         if (!W_ERROR_IS_OK(result)) {
7194                 return result;
7195         }
7196
7197         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7198                                                      spoolss_EnumJobs,
7199                                                      *r->out.info, r->in.level,
7200                                                      *r->out.count);
7201         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7202         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7203
7204         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7205 }
7206
7207 /****************************************************************
7208  _spoolss_ScheduleJob
7209 ****************************************************************/
7210
7211 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7212                             struct spoolss_ScheduleJob *r)
7213 {
7214         return WERR_OK;
7215 }
7216
7217 /****************************************************************
7218 ****************************************************************/
7219
7220 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7221                                struct messaging_context *msg_ctx,
7222                                const char *printer_name,
7223                                uint32_t job_id,
7224                                struct spoolss_SetJobInfo1 *r)
7225 {
7226         char *old_doc_name;
7227
7228         if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7229                 return WERR_BADFID;
7230         }
7231
7232         if (strequal(old_doc_name, r->document_name)) {
7233                 return WERR_OK;
7234         }
7235
7236         if (!print_job_set_name(server_event_context(), msg_ctx,
7237                                 printer_name, job_id, r->document_name)) {
7238                 return WERR_BADFID;
7239         }
7240
7241         return WERR_OK;
7242 }
7243
7244 /****************************************************************
7245  _spoolss_SetJob
7246 ****************************************************************/
7247
7248 WERROR _spoolss_SetJob(struct pipes_struct *p,
7249                        struct spoolss_SetJob *r)
7250 {
7251         const struct auth_serversupplied_info *session_info = p->session_info;
7252         int snum;
7253         WERROR errcode = WERR_BADFUNC;
7254
7255         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7256                 return WERR_BADFID;
7257         }
7258
7259         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7260                 return WERR_INVALID_PRINTER_NAME;
7261         }
7262
7263         switch (r->in.command) {
7264         case SPOOLSS_JOB_CONTROL_CANCEL:
7265         case SPOOLSS_JOB_CONTROL_DELETE:
7266                 errcode = print_job_delete(session_info, p->msg_ctx,
7267                                            snum, r->in.job_id);
7268                 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7269                         errcode = WERR_OK;
7270                 }
7271                 break;
7272         case SPOOLSS_JOB_CONTROL_PAUSE:
7273                 if (print_job_pause(session_info, p->msg_ctx,
7274                                     snum, r->in.job_id, &errcode)) {
7275                         errcode = WERR_OK;
7276                 }
7277                 break;
7278         case SPOOLSS_JOB_CONTROL_RESTART:
7279         case SPOOLSS_JOB_CONTROL_RESUME:
7280                 if (print_job_resume(session_info, p->msg_ctx,
7281                                      snum, r->in.job_id, &errcode)) {
7282                         errcode = WERR_OK;
7283                 }
7284                 break;
7285         case 0:
7286                 errcode = WERR_OK;
7287                 break;
7288         default:
7289                 return WERR_UNKNOWN_LEVEL;
7290         }
7291
7292         if (!W_ERROR_IS_OK(errcode)) {
7293                 return errcode;
7294         }
7295
7296         if (r->in.ctr == NULL) {
7297                 return errcode;
7298         }
7299
7300         switch (r->in.ctr->level) {
7301         case 1:
7302                 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7303                                            lp_const_servicename(snum),
7304                                            r->in.job_id,
7305                                            r->in.ctr->info.info1);
7306                 break;
7307         case 2:
7308         case 3:
7309         case 4:
7310         default:
7311                 return WERR_UNKNOWN_LEVEL;
7312         }
7313
7314         return errcode;
7315 }
7316
7317 /****************************************************************************
7318  Enumerates all printer drivers by level and architecture.
7319 ****************************************************************************/
7320
7321 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7322                                                        const struct auth_serversupplied_info *session_info,
7323                                                        struct messaging_context *msg_ctx,
7324                                                        const char *servername,
7325                                                        const char *architecture,
7326                                                        uint32_t level,
7327                                                        union spoolss_DriverInfo **info_p,
7328                                                        uint32_t *count_p)
7329 {
7330         int i;
7331         uint32_t version;
7332         struct spoolss_DriverInfo8 *driver;
7333         union spoolss_DriverInfo *info = NULL;
7334         uint32_t count = 0;
7335         WERROR result = WERR_OK;
7336         uint32_t num_drivers;
7337         const char **drivers;
7338         struct dcerpc_binding_handle *b;
7339
7340         *count_p = 0;
7341         *info_p = NULL;
7342
7343         result = winreg_printer_binding_handle(mem_ctx,
7344                                                session_info,
7345                                                msg_ctx,
7346                                                &b);
7347         if (!W_ERROR_IS_OK(result)) {
7348                 goto out;
7349         }
7350
7351         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7352                 result = winreg_get_driver_list(mem_ctx, b,
7353                                                 architecture, version,
7354                                                 &num_drivers, &drivers);
7355                 if (!W_ERROR_IS_OK(result)) {
7356                         goto out;
7357                 }
7358                 DEBUG(4, ("we have:[%d] drivers in environment"
7359                           " [%s] and version [%d]\n",
7360                           num_drivers, architecture, version));
7361
7362                 if (num_drivers != 0) {
7363                         info = talloc_realloc(mem_ctx, info,
7364                                                     union spoolss_DriverInfo,
7365                                                     count + num_drivers);
7366                         if (!info) {
7367                                 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7368                                         "failed to enlarge driver info buffer!\n"));
7369                                 result = WERR_NOMEM;
7370                                 goto out;
7371                         }
7372                 }
7373
7374                 for (i = 0; i < num_drivers; i++) {
7375                         DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7376
7377                         result = winreg_get_driver(mem_ctx, b,
7378                                                    architecture, drivers[i],
7379                                                    version, &driver);
7380                         if (!W_ERROR_IS_OK(result)) {
7381                                 goto out;
7382                         }
7383
7384                         switch (level) {
7385                         case 1:
7386                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
7387                                                                    driver, servername);
7388                                 break;
7389                         case 2:
7390                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
7391                                                                    driver, servername);
7392                                 break;
7393                         case 3:
7394                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
7395                                                                    driver, servername);
7396                                 break;
7397                         case 4:
7398                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
7399                                                                    driver, servername);
7400                                 break;
7401                         case 5:
7402                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
7403                                                                    driver, servername);
7404                                 break;
7405                         case 6:
7406                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
7407                                                                    driver, servername);
7408                                 break;
7409                         case 8:
7410                                 result = fill_printer_driver_info8(info, &info[count+i].info8,
7411                                                                    driver, servername);
7412                                 break;
7413                         default:
7414                                 result = WERR_UNKNOWN_LEVEL;
7415                                 break;
7416                         }
7417
7418                         TALLOC_FREE(driver);
7419
7420                         if (!W_ERROR_IS_OK(result)) {
7421                                 goto out;
7422                         }
7423                 }
7424
7425                 count += num_drivers;
7426                 TALLOC_FREE(drivers);
7427         }
7428
7429  out:
7430         TALLOC_FREE(drivers);
7431
7432         if (!W_ERROR_IS_OK(result)) {
7433                 TALLOC_FREE(info);
7434                 return result;
7435         }
7436
7437         *info_p = info;
7438         *count_p = count;
7439
7440         return WERR_OK;
7441 }
7442
7443 /****************************************************************************
7444  Enumerates all printer drivers by level.
7445 ****************************************************************************/
7446
7447 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7448                                        const struct auth_serversupplied_info *session_info,
7449                                        struct messaging_context *msg_ctx,
7450                                        const char *servername,
7451                                        const char *architecture,
7452                                        uint32_t level,
7453                                        union spoolss_DriverInfo **info_p,
7454                                        uint32_t *count_p)
7455 {
7456         uint32_t a,i;
7457         WERROR result = WERR_OK;
7458
7459         if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7460
7461                 for (a=0; archi_table[a].long_archi != NULL; a++) {
7462
7463                         union spoolss_DriverInfo *info = NULL;
7464                         uint32_t count = 0;
7465
7466                         result = enumprinterdrivers_level_by_architecture(mem_ctx,
7467                                                                           session_info,
7468                                                                           msg_ctx,
7469                                                                           servername,
7470                                                                           archi_table[a].long_archi,
7471                                                                           level,
7472                                                                           &info,
7473                                                                           &count);
7474                         if (!W_ERROR_IS_OK(result)) {
7475                                 continue;
7476                         }
7477
7478                         for (i=0; i < count; i++) {
7479                                 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7480                                              info[i], info_p, count_p);
7481                         }
7482                 }
7483
7484                 return result;
7485         }
7486
7487         return enumprinterdrivers_level_by_architecture(mem_ctx,
7488                                                         session_info,
7489                                                         msg_ctx,
7490                                                         servername,
7491                                                         architecture,
7492                                                         level,
7493                                                         info_p,
7494                                                         count_p);
7495 }
7496
7497 /****************************************************************
7498  _spoolss_EnumPrinterDrivers
7499 ****************************************************************/
7500
7501 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7502                                    struct spoolss_EnumPrinterDrivers *r)
7503 {
7504         const char *cservername;
7505         WERROR result;
7506
7507         /* that's an [in out] buffer */
7508
7509         if (!r->in.buffer && (r->in.offered != 0)) {
7510                 return WERR_INVALID_PARAM;
7511         }
7512
7513         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7514
7515         *r->out.needed = 0;
7516         *r->out.count = 0;
7517         *r->out.info = NULL;
7518
7519         cservername = canon_servername(r->in.server);
7520
7521         if (!is_myname_or_ipaddr(cservername)) {
7522                 return WERR_UNKNOWN_PRINTER_DRIVER;
7523         }
7524
7525         result = enumprinterdrivers_level(p->mem_ctx,
7526                                           get_session_info_system(),
7527                                           p->msg_ctx,
7528                                           cservername,
7529                                           r->in.environment,
7530                                           r->in.level,
7531                                           r->out.info,
7532                                           r->out.count);
7533         if (!W_ERROR_IS_OK(result)) {
7534                 return result;
7535         }
7536
7537         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7538                                                      spoolss_EnumPrinterDrivers,
7539                                                      *r->out.info, r->in.level,
7540                                                      *r->out.count);
7541         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7542         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7543
7544         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7545 }
7546
7547 /****************************************************************
7548  _spoolss_EnumForms
7549 ****************************************************************/
7550
7551 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7552                           struct spoolss_EnumForms *r)
7553 {
7554         WERROR result;
7555
7556         *r->out.count = 0;
7557         *r->out.needed = 0;
7558         *r->out.info = NULL;
7559
7560         /* that's an [in out] buffer */
7561
7562         if (!r->in.buffer && (r->in.offered != 0) ) {
7563                 return WERR_INVALID_PARAM;
7564         }
7565
7566         DEBUG(4,("_spoolss_EnumForms\n"));
7567         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7568         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7569
7570         switch (r->in.level) {
7571         case 1:
7572                 result = winreg_printer_enumforms1_internal(p->mem_ctx,
7573                                                    get_session_info_system(),
7574                                                    p->msg_ctx,
7575                                                    r->out.count,
7576                                                    r->out.info);
7577                 break;
7578         default:
7579                 result = WERR_UNKNOWN_LEVEL;
7580                 break;
7581         }
7582
7583         if (!W_ERROR_IS_OK(result)) {
7584                 return result;
7585         }
7586
7587         if (*r->out.count == 0) {
7588                 return WERR_NO_MORE_ITEMS;
7589         }
7590
7591         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7592                                                      spoolss_EnumForms,
7593                                                      *r->out.info, r->in.level,
7594                                                      *r->out.count);
7595         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7596         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7597
7598         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7599 }
7600
7601 /****************************************************************
7602  _spoolss_GetForm
7603 ****************************************************************/
7604
7605 WERROR _spoolss_GetForm(struct pipes_struct *p,
7606                         struct spoolss_GetForm *r)
7607 {
7608         WERROR result;
7609
7610         /* that's an [in out] buffer */
7611
7612         if (!r->in.buffer && (r->in.offered != 0)) {
7613                 return WERR_INVALID_PARAM;
7614         }
7615
7616         DEBUG(4,("_spoolss_GetForm\n"));
7617         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7618         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7619
7620         switch (r->in.level) {
7621         case 1:
7622                 result = winreg_printer_getform1_internal(p->mem_ctx,
7623                                                  get_session_info_system(),
7624                                                  p->msg_ctx,
7625                                                  r->in.form_name,
7626                                                  &r->out.info->info1);
7627                 break;
7628         default:
7629                 result = WERR_UNKNOWN_LEVEL;
7630                 break;
7631         }
7632
7633         if (!W_ERROR_IS_OK(result)) {
7634                 TALLOC_FREE(r->out.info);
7635                 return result;
7636         }
7637
7638         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
7639                                                r->out.info, r->in.level);
7640         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7641
7642         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7643 }
7644
7645 /****************************************************************************
7646 ****************************************************************************/
7647
7648 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7649                           struct spoolss_PortInfo1 *r,
7650                           const char *name)
7651 {
7652         r->port_name = talloc_strdup(mem_ctx, name);
7653         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7654
7655         return WERR_OK;
7656 }
7657
7658 /****************************************************************************
7659  TODO: This probably needs distinguish between TCP/IP and Local ports
7660  somehow.
7661 ****************************************************************************/
7662
7663 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7664                           struct spoolss_PortInfo2 *r,
7665                           const char *name)
7666 {
7667         r->port_name = talloc_strdup(mem_ctx, name);
7668         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7669
7670         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7671         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7672
7673         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7674         W_ERROR_HAVE_NO_MEMORY(r->description);
7675
7676         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7677         r->reserved = 0;
7678
7679         return WERR_OK;
7680 }
7681
7682
7683 /****************************************************************************
7684  wrapper around the enumer ports command
7685 ****************************************************************************/
7686
7687 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7688 {
7689         char *cmd = lp_enumports_cmd();
7690         char **qlines = NULL;
7691         char *command = NULL;
7692         int numlines;
7693         int ret;
7694         int fd;
7695
7696         *count = 0;
7697         *lines = NULL;
7698
7699         /* if no hook then just fill in the default port */
7700
7701         if ( !*cmd ) {
7702                 if (!(qlines = talloc_array( NULL, char*, 2 ))) {
7703                         return WERR_NOMEM;
7704                 }
7705                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7706                         TALLOC_FREE(qlines);
7707                         return WERR_NOMEM;
7708                 }
7709                 qlines[1] = NULL;
7710                 numlines = 1;
7711         }
7712         else {
7713                 /* we have a valid enumport command */
7714
7715                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7716                 if (!command) {
7717                         return WERR_NOMEM;
7718                 }
7719
7720                 DEBUG(10,("Running [%s]\n", command));
7721                 ret = smbrun(command, &fd);
7722                 DEBUG(10,("Returned [%d]\n", ret));
7723                 TALLOC_FREE(command);
7724                 if (ret != 0) {
7725                         if (fd != -1) {
7726                                 close(fd);
7727                         }
7728                         return WERR_ACCESS_DENIED;
7729                 }
7730
7731                 numlines = 0;
7732                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7733                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7734                 close(fd);
7735         }
7736
7737         *count = numlines;
7738         *lines = qlines;
7739
7740         return WERR_OK;
7741 }
7742
7743 /****************************************************************************
7744  enumports level 1.
7745 ****************************************************************************/
7746
7747 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7748                                 union spoolss_PortInfo **info_p,
7749                                 uint32_t *count)
7750 {
7751         union spoolss_PortInfo *info = NULL;
7752         int i=0;
7753         WERROR result = WERR_OK;
7754         char **qlines = NULL;
7755         int numlines = 0;
7756
7757         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7758         if (!W_ERROR_IS_OK(result)) {
7759                 goto out;
7760         }
7761
7762         if (numlines) {
7763                 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
7764                 if (!info) {
7765                         DEBUG(10,("Returning WERR_NOMEM\n"));
7766                         result = WERR_NOMEM;
7767                         goto out;
7768                 }
7769
7770                 for (i=0; i<numlines; i++) {
7771                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7772                         result = fill_port_1(info, &info[i].info1, qlines[i]);
7773                         if (!W_ERROR_IS_OK(result)) {
7774                                 goto out;
7775                         }
7776                 }
7777         }
7778         TALLOC_FREE(qlines);
7779
7780 out:
7781         if (!W_ERROR_IS_OK(result)) {
7782                 TALLOC_FREE(info);
7783                 TALLOC_FREE(qlines);
7784                 *count = 0;
7785                 *info_p = NULL;
7786                 return result;
7787         }
7788
7789         *info_p = info;
7790         *count = numlines;
7791
7792         return WERR_OK;
7793 }
7794
7795 /****************************************************************************
7796  enumports level 2.
7797 ****************************************************************************/
7798
7799 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7800                                 union spoolss_PortInfo **info_p,
7801                                 uint32_t *count)
7802 {
7803         union spoolss_PortInfo *info = NULL;
7804         int i=0;
7805         WERROR result = WERR_OK;
7806         char **qlines = NULL;
7807         int numlines = 0;
7808
7809         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7810         if (!W_ERROR_IS_OK(result)) {
7811                 goto out;
7812         }
7813
7814         if (numlines) {
7815                 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
7816                 if (!info) {
7817                         DEBUG(10,("Returning WERR_NOMEM\n"));
7818                         result = WERR_NOMEM;
7819                         goto out;
7820                 }
7821
7822                 for (i=0; i<numlines; i++) {
7823                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7824                         result = fill_port_2(info, &info[i].info2, qlines[i]);
7825                         if (!W_ERROR_IS_OK(result)) {
7826                                 goto out;
7827                         }
7828                 }
7829         }
7830         TALLOC_FREE(qlines);
7831
7832 out:
7833         if (!W_ERROR_IS_OK(result)) {
7834                 TALLOC_FREE(info);
7835                 TALLOC_FREE(qlines);
7836                 *count = 0;
7837                 *info_p = NULL;
7838                 return result;
7839         }
7840
7841         *info_p = info;
7842         *count = numlines;
7843
7844         return WERR_OK;
7845 }
7846
7847 /****************************************************************
7848  _spoolss_EnumPorts
7849 ****************************************************************/
7850
7851 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
7852                           struct spoolss_EnumPorts *r)
7853 {
7854         WERROR result;
7855
7856         /* that's an [in out] buffer */
7857
7858         if (!r->in.buffer && (r->in.offered != 0)) {
7859                 return WERR_INVALID_PARAM;
7860         }
7861
7862         DEBUG(4,("_spoolss_EnumPorts\n"));
7863
7864         *r->out.count = 0;
7865         *r->out.needed = 0;
7866         *r->out.info = NULL;
7867
7868         switch (r->in.level) {
7869         case 1:
7870                 result = enumports_level_1(p->mem_ctx, r->out.info,
7871                                            r->out.count);
7872                 break;
7873         case 2:
7874                 result = enumports_level_2(p->mem_ctx, r->out.info,
7875                                            r->out.count);
7876                 break;
7877         default:
7878                 return WERR_UNKNOWN_LEVEL;
7879         }
7880
7881         if (!W_ERROR_IS_OK(result)) {
7882                 return result;
7883         }
7884
7885         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7886                                                      spoolss_EnumPorts,
7887                                                      *r->out.info, r->in.level,
7888                                                      *r->out.count);
7889         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7890         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7891
7892         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7893 }
7894
7895 /****************************************************************************
7896 ****************************************************************************/
7897
7898 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
7899                                            const char *server,
7900                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
7901                                            struct spoolss_DeviceMode *devmode,
7902                                            struct security_descriptor *secdesc,
7903                                            struct spoolss_UserLevelCtr *user_ctr,
7904                                            struct policy_handle *handle)
7905 {
7906         struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
7907         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
7908         int     snum;
7909         WERROR err = WERR_OK;
7910
7911         /* samba does not have a concept of local, non-shared printers yet, so
7912          * make sure we always setup sharename - gd */
7913         if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
7914             (info2->printername != NULL && info2->printername[0] != '\0')) {
7915                 DEBUG(5, ("spoolss_addprinterex_level_2: "
7916                         "no sharename has been set, setting printername %s as sharename\n",
7917                         info2->printername));
7918                 info2->sharename = info2->printername;
7919         }
7920
7921         /* check to see if the printer already exists */
7922         if ((snum = print_queue_snum(info2->sharename)) != -1) {
7923                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7924                         info2->sharename));
7925                 return WERR_PRINTER_ALREADY_EXISTS;
7926         }
7927
7928         if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7929                 if ((snum = print_queue_snum(info2->printername)) != -1) {
7930                         DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7931                                 info2->printername));
7932                         return WERR_PRINTER_ALREADY_EXISTS;
7933                 }
7934         }
7935
7936         /* validate printer info struct */
7937         if (!info2->printername || strlen(info2->printername) == 0) {
7938                 return WERR_INVALID_PRINTER_NAME;
7939         }
7940         if (!info2->portname || strlen(info2->portname) == 0) {
7941                 return WERR_UNKNOWN_PORT;
7942         }
7943         if (!info2->drivername || strlen(info2->drivername) == 0) {
7944                 return WERR_UNKNOWN_PRINTER_DRIVER;
7945         }
7946         if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
7947                 return WERR_UNKNOWN_PRINTPROCESSOR;
7948         }
7949
7950         /* FIXME!!!  smbd should check to see if the driver is installed before
7951            trying to add a printer like this  --jerry */
7952
7953         if (*lp_addprinter_cmd() ) {
7954                 char *raddr;
7955
7956                 raddr = tsocket_address_inet_addr_string(p->remote_address,
7957                                                          p->mem_ctx);
7958                 if (raddr == NULL) {
7959                         return WERR_NOMEM;
7960                 }
7961
7962                 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
7963                                        info2, raddr,
7964                                        p->msg_ctx) ) {
7965                         return WERR_ACCESS_DENIED;
7966                 }
7967         } else {
7968                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
7969                         "smb.conf parameter \"addprinter command\" is defined. This "
7970                         "parameter must exist for this call to succeed\n",
7971                         info2->sharename ));
7972         }
7973
7974         if ((snum = print_queue_snum(info2->sharename)) == -1) {
7975                 return WERR_ACCESS_DENIED;
7976         }
7977
7978         /* you must be a printer admin to add a new printer */
7979         if (!print_access_check(p->session_info,
7980                                 p->msg_ctx,
7981                                 snum,
7982                                 PRINTER_ACCESS_ADMINISTER)) {
7983                 return WERR_ACCESS_DENIED;
7984         }
7985
7986         /*
7987          * Do sanity check on the requested changes for Samba.
7988          */
7989
7990         if (!check_printer_ok(p->mem_ctx, info2, snum)) {
7991                 return WERR_INVALID_PARAM;
7992         }
7993
7994         if (devmode == NULL) {
7995                 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
7996         }
7997
7998         update_dsspooler(p->mem_ctx,
7999                          get_session_info_system(),
8000                          p->msg_ctx,
8001                          0,
8002                          info2,
8003                          NULL);
8004
8005         err = winreg_update_printer_internal(p->mem_ctx,
8006                                     get_session_info_system(),
8007                                     p->msg_ctx,
8008                                     info2->sharename,
8009                                     info2_mask,
8010                                     info2,
8011                                     devmode,
8012                                     secdesc);
8013         if (!W_ERROR_IS_OK(err)) {
8014                 return err;
8015         }
8016
8017         err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
8018         if (!W_ERROR_IS_OK(err)) {
8019                 /* Handle open failed - remove addition. */
8020                 ZERO_STRUCTP(handle);
8021                 return err;
8022         }
8023
8024         return WERR_OK;
8025 }
8026
8027 /****************************************************************
8028  _spoolss_AddPrinterEx
8029 ****************************************************************/
8030
8031 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
8032                              struct spoolss_AddPrinterEx *r)
8033 {
8034         switch (r->in.info_ctr->level) {
8035         case 1:
8036                 /* we don't handle yet */
8037                 /* but I know what to do ... */
8038                 return WERR_UNKNOWN_LEVEL;
8039         case 2:
8040                 return spoolss_addprinterex_level_2(p, r->in.server,
8041                                                     r->in.info_ctr,
8042                                                     r->in.devmode_ctr->devmode,
8043                                                     r->in.secdesc_ctr->sd,
8044                                                     r->in.userlevel_ctr,
8045                                                     r->out.handle);
8046         default:
8047                 return WERR_UNKNOWN_LEVEL;
8048         }
8049 }
8050
8051 /****************************************************************
8052  _spoolss_AddPrinter
8053 ****************************************************************/
8054
8055 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
8056                            struct spoolss_AddPrinter *r)
8057 {
8058         struct spoolss_AddPrinterEx a;
8059         struct spoolss_UserLevelCtr userlevel_ctr;
8060
8061         ZERO_STRUCT(userlevel_ctr);
8062
8063         userlevel_ctr.level = 1;
8064
8065         a.in.server             = r->in.server;
8066         a.in.info_ctr           = r->in.info_ctr;
8067         a.in.devmode_ctr        = r->in.devmode_ctr;
8068         a.in.secdesc_ctr        = r->in.secdesc_ctr;
8069         a.in.userlevel_ctr      = &userlevel_ctr;
8070         a.out.handle            = r->out.handle;
8071
8072         return _spoolss_AddPrinterEx(p, &a);
8073 }
8074
8075 /****************************************************************
8076  _spoolss_AddPrinterDriverEx
8077 ****************************************************************/
8078
8079 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
8080                                    struct spoolss_AddPrinterDriverEx *r)
8081 {
8082         WERROR err = WERR_OK;
8083         const char *driver_name = NULL;
8084         uint32_t version;
8085         const char *fn;
8086
8087         switch (p->opnum) {
8088                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
8089                         fn = "_spoolss_AddPrinterDriver";
8090                         break;
8091                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
8092                         fn = "_spoolss_AddPrinterDriverEx";
8093                         break;
8094                 default:
8095                         return WERR_INVALID_PARAM;
8096         }
8097
8098         /*
8099          * we only support the semantics of AddPrinterDriver()
8100          * i.e. only copy files that are newer than existing ones
8101          */
8102
8103         if (r->in.flags == 0) {
8104                 return WERR_INVALID_PARAM;
8105         }
8106
8107         if (r->in.flags != APD_COPY_NEW_FILES) {
8108                 return WERR_ACCESS_DENIED;
8109         }
8110
8111         /* FIXME */
8112         if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
8113                 /* Clever hack from Martin Zielinski <mz@seh.de>
8114                  * to allow downgrade from level 8 (Vista).
8115                  */
8116                 DEBUG(0,("%s: level %d not yet implemented\n", fn,
8117                         r->in.info_ctr->level));
8118                 return WERR_UNKNOWN_LEVEL;
8119         }
8120
8121         DEBUG(5,("Cleaning driver's information\n"));
8122         err = clean_up_driver_struct(p->mem_ctx, p->session_info, r->in.info_ctr);
8123         if (!W_ERROR_IS_OK(err))
8124                 goto done;
8125
8126         DEBUG(5,("Moving driver to final destination\n"));
8127         err = move_driver_to_download_area(p->session_info, r->in.info_ctr);
8128         if (!W_ERROR_IS_OK(err)) {
8129                 goto done;
8130         }
8131
8132         err = winreg_add_driver_internal(p->mem_ctx,
8133                                 get_session_info_system(),
8134                                 p->msg_ctx,
8135                                 r->in.info_ctr,
8136                                 &driver_name,
8137                                 &version);
8138         if (!W_ERROR_IS_OK(err)) {
8139                 goto done;
8140         }
8141
8142         /*
8143          * I think this is where he DrvUpgradePrinter() hook would be
8144          * be called in a driver's interface DLL on a Windows NT 4.0/2k
8145          * server.  Right now, we just need to send ourselves a message
8146          * to update each printer bound to this driver.   --jerry
8147          */
8148
8149         if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8150                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8151                         fn, driver_name));
8152         }
8153
8154 done:
8155         return err;
8156 }
8157
8158 /****************************************************************
8159  _spoolss_AddPrinterDriver
8160 ****************************************************************/
8161
8162 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8163                                  struct spoolss_AddPrinterDriver *r)
8164 {
8165         struct spoolss_AddPrinterDriverEx a;
8166
8167         switch (r->in.info_ctr->level) {
8168         case 2:
8169         case 3:
8170         case 4:
8171         case 5:
8172                 break;
8173         default:
8174                 return WERR_UNKNOWN_LEVEL;
8175         }
8176
8177         a.in.servername         = r->in.servername;
8178         a.in.info_ctr           = r->in.info_ctr;
8179         a.in.flags              = APD_COPY_NEW_FILES;
8180
8181         return _spoolss_AddPrinterDriverEx(p, &a);
8182 }
8183
8184 /****************************************************************************
8185 ****************************************************************************/
8186
8187 struct _spoolss_paths {
8188         int type;
8189         const char *share;
8190         const char *dir;
8191 };
8192
8193 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8194
8195 static const struct _spoolss_paths spoolss_paths[]= {
8196         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
8197         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
8198 };
8199
8200 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8201                                           const char *servername,
8202                                           const char *environment,
8203                                           int component,
8204                                           char **path)
8205 {
8206         const char *pservername = NULL;
8207         const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
8208         const char *short_archi;
8209
8210         *path = NULL;
8211
8212         /* environment may be empty */
8213         if (environment && strlen(environment)) {
8214                 long_archi = environment;
8215         }
8216
8217         /* servername may be empty */
8218         if (servername && strlen(servername)) {
8219                 pservername = canon_servername(servername);
8220
8221                 if (!is_myname_or_ipaddr(pservername)) {
8222                         return WERR_INVALID_PARAM;
8223                 }
8224         }
8225
8226         if (!(short_archi = get_short_archi(long_archi))) {
8227                 return WERR_INVALID_ENVIRONMENT;
8228         }
8229
8230         switch (component) {
8231         case SPOOLSS_PRTPROCS_PATH:
8232         case SPOOLSS_DRIVER_PATH:
8233                 if (pservername) {
8234                         *path = talloc_asprintf(mem_ctx,
8235                                         "\\\\%s\\%s\\%s",
8236                                         pservername,
8237                                         spoolss_paths[component].share,
8238                                         short_archi);
8239                 } else {
8240                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8241                                         SPOOLSS_DEFAULT_SERVER_PATH,
8242                                         spoolss_paths[component].dir,
8243                                         short_archi);
8244                 }
8245                 break;
8246         default:
8247                 return WERR_INVALID_PARAM;
8248         }
8249
8250         if (!*path) {
8251                 return WERR_NOMEM;
8252         }
8253
8254         return WERR_OK;
8255 }
8256
8257 /****************************************************************************
8258 ****************************************************************************/
8259
8260 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8261                                           const char *servername,
8262                                           const char *environment,
8263                                           struct spoolss_DriverDirectoryInfo1 *r)
8264 {
8265         WERROR werr;
8266         char *path = NULL;
8267
8268         werr = compose_spoolss_server_path(mem_ctx,
8269                                            servername,
8270                                            environment,
8271                                            SPOOLSS_DRIVER_PATH,
8272                                            &path);
8273         if (!W_ERROR_IS_OK(werr)) {
8274                 return werr;
8275         }
8276
8277         DEBUG(4,("printer driver directory: [%s]\n", path));
8278
8279         r->directory_name = path;
8280
8281         return WERR_OK;
8282 }
8283
8284 /****************************************************************
8285  _spoolss_GetPrinterDriverDirectory
8286 ****************************************************************/
8287
8288 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8289                                           struct spoolss_GetPrinterDriverDirectory *r)
8290 {
8291         WERROR werror;
8292
8293         /* that's an [in out] buffer */
8294
8295         if (!r->in.buffer && (r->in.offered != 0)) {
8296                 return WERR_INVALID_PARAM;
8297         }
8298
8299         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8300                 r->in.level));
8301
8302         *r->out.needed = 0;
8303
8304         /* r->in.level is ignored */
8305
8306         werror = getprinterdriverdir_level_1(p->mem_ctx,
8307                                              r->in.server,
8308                                              r->in.environment,
8309                                              &r->out.info->info1);
8310         if (!W_ERROR_IS_OK(werror)) {
8311                 TALLOC_FREE(r->out.info);
8312                 return werror;
8313         }
8314
8315         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8316                                                r->out.info, r->in.level);
8317         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8318
8319         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8320 }
8321
8322 /****************************************************************
8323  _spoolss_EnumPrinterData
8324 ****************************************************************/
8325
8326 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8327                                 struct spoolss_EnumPrinterData *r)
8328 {
8329         WERROR result;
8330         struct spoolss_EnumPrinterDataEx r2;
8331         uint32_t count;
8332         struct spoolss_PrinterEnumValues *info, *val = NULL;
8333         uint32_t needed;
8334
8335         r2.in.handle    = r->in.handle;
8336         r2.in.key_name  = "PrinterDriverData";
8337         r2.in.offered   = 0;
8338         r2.out.count    = &count;
8339         r2.out.info     = &info;
8340         r2.out.needed   = &needed;
8341
8342         result = _spoolss_EnumPrinterDataEx(p, &r2);
8343         if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8344                 r2.in.offered = needed;
8345                 result = _spoolss_EnumPrinterDataEx(p, &r2);
8346         }
8347         if (!W_ERROR_IS_OK(result)) {
8348                 return result;
8349         }
8350
8351         /*
8352          * The NT machine wants to know the biggest size of value and data
8353          *
8354          * cf: MSDN EnumPrinterData remark section
8355          */
8356
8357         if (!r->in.value_offered && !r->in.data_offered) {
8358                 uint32_t biggest_valuesize = 0;
8359                 uint32_t biggest_datasize = 0;
8360                 int i, name_length;
8361
8362                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8363
8364                 for (i=0; i<count; i++) {
8365
8366                         name_length = strlen(info[i].value_name);
8367                         if (strlen(info[i].value_name) > biggest_valuesize) {
8368                                 biggest_valuesize = name_length;
8369                         }
8370
8371                         if (info[i].data_length > biggest_datasize) {
8372                                 biggest_datasize = info[i].data_length;
8373                         }
8374
8375                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8376                                 biggest_datasize));
8377                 }
8378
8379                 /* the value is an UNICODE string but real_value_size is the length
8380                    in bytes including the trailing 0 */
8381
8382                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8383                 *r->out.data_needed  = biggest_datasize;
8384
8385                 DEBUG(6,("final values: [%d], [%d]\n",
8386                         *r->out.value_needed, *r->out.data_needed));
8387
8388                 return WERR_OK;
8389         }
8390
8391         if (r->in.enum_index < count) {
8392                 val = &info[r->in.enum_index];
8393         }
8394
8395         if (val == NULL) {
8396                 /* out_value should default to "" or else NT4 has
8397                    problems unmarshalling the response */
8398
8399                 if (r->in.value_offered) {
8400                         *r->out.value_needed = 1;
8401                         r->out.value_name = talloc_strdup(r, "");
8402                         if (!r->out.value_name) {
8403                                 return WERR_NOMEM;
8404                         }
8405                 } else {
8406                         r->out.value_name = NULL;
8407                         *r->out.value_needed = 0;
8408                 }
8409
8410                 /* the data is counted in bytes */
8411
8412                 *r->out.data_needed = r->in.data_offered;
8413
8414                 result = WERR_NO_MORE_ITEMS;
8415         } else {
8416                 /*
8417                  * the value is:
8418                  * - counted in bytes in the request
8419                  * - counted in UNICODE chars in the max reply
8420                  * - counted in bytes in the real size
8421                  *
8422                  * take a pause *before* coding not *during* coding
8423                  */
8424
8425                 /* name */
8426                 if (r->in.value_offered) {
8427                         r->out.value_name = talloc_strdup(r, val->value_name);
8428                         if (!r->out.value_name) {
8429                                 return WERR_NOMEM;
8430                         }
8431                         *r->out.value_needed = val->value_name_len;
8432                 } else {
8433                         r->out.value_name = NULL;
8434                         *r->out.value_needed = 0;
8435                 }
8436
8437                 /* type */
8438
8439                 *r->out.type = val->type;
8440
8441                 /* data - counted in bytes */
8442
8443                 /*
8444                  * See the section "Dynamically Typed Query Parameters"
8445                  * in MS-RPRN.
8446                  */
8447
8448                 if (r->out.data && val->data && val->data->data &&
8449                                 val->data_length && r->in.data_offered) {
8450                         memcpy(r->out.data, val->data->data,
8451                                 MIN(val->data_length,r->in.data_offered));
8452                 }
8453
8454                 *r->out.data_needed = val->data_length;
8455
8456                 result = WERR_OK;
8457         }
8458
8459         return result;
8460 }
8461
8462 /****************************************************************
8463  _spoolss_SetPrinterData
8464 ****************************************************************/
8465
8466 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8467                                struct spoolss_SetPrinterData *r)
8468 {
8469         struct spoolss_SetPrinterDataEx r2;
8470
8471         r2.in.handle            = r->in.handle;
8472         r2.in.key_name          = "PrinterDriverData";
8473         r2.in.value_name        = r->in.value_name;
8474         r2.in.type              = r->in.type;
8475         r2.in.data              = r->in.data;
8476         r2.in.offered           = r->in.offered;
8477
8478         return _spoolss_SetPrinterDataEx(p, &r2);
8479 }
8480
8481 /****************************************************************
8482  _spoolss_ResetPrinter
8483 ****************************************************************/
8484
8485 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8486                              struct spoolss_ResetPrinter *r)
8487 {
8488         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8489         int             snum;
8490
8491         DEBUG(5,("_spoolss_ResetPrinter\n"));
8492
8493         /*
8494          * All we do is to check to see if the handle and queue is valid.
8495          * This call really doesn't mean anything to us because we only
8496          * support RAW printing.   --jerry
8497          */
8498
8499         if (!Printer) {
8500                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8501                         OUR_HANDLE(r->in.handle)));
8502                 return WERR_BADFID;
8503         }
8504
8505         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8506                 return WERR_BADFID;
8507
8508
8509         /* blindly return success */
8510         return WERR_OK;
8511 }
8512
8513 /****************************************************************
8514  _spoolss_DeletePrinterData
8515 ****************************************************************/
8516
8517 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8518                                   struct spoolss_DeletePrinterData *r)
8519 {
8520         struct spoolss_DeletePrinterDataEx r2;
8521
8522         r2.in.handle            = r->in.handle;
8523         r2.in.key_name          = "PrinterDriverData";
8524         r2.in.value_name        = r->in.value_name;
8525
8526         return _spoolss_DeletePrinterDataEx(p, &r2);
8527 }
8528
8529 /****************************************************************
8530  _spoolss_AddForm
8531 ****************************************************************/
8532
8533 WERROR _spoolss_AddForm(struct pipes_struct *p,
8534                         struct spoolss_AddForm *r)
8535 {
8536         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8537         int snum = -1;
8538         WERROR status = WERR_OK;
8539         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8540         struct dcerpc_binding_handle *b;
8541
8542         DEBUG(5,("_spoolss_AddForm\n"));
8543
8544         if (!Printer) {
8545                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8546                         OUR_HANDLE(r->in.handle)));
8547                 return WERR_BADFID;
8548         }
8549
8550         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8551            and not a printer admin, then fail */
8552
8553         if ((p->session_info->utok.uid != sec_initial_uid()) &&
8554             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8555             !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8556                                           p->session_info->info3->base.domain.string,
8557                                           NULL,
8558                                           p->session_info->security_token,
8559                                           lp_printer_admin(snum))) {
8560                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8561                 return WERR_ACCESS_DENIED;
8562         }
8563
8564         switch (form->flags) {
8565         case SPOOLSS_FORM_USER:
8566         case SPOOLSS_FORM_BUILTIN:
8567         case SPOOLSS_FORM_PRINTER:
8568                 break;
8569         default:
8570                 return WERR_INVALID_PARAM;
8571         }
8572
8573         status = winreg_printer_binding_handle(p->mem_ctx,
8574                                                get_session_info_system(),
8575                                                p->msg_ctx,
8576                                                &b);
8577         if (!W_ERROR_IS_OK(status)) {
8578                 return status;
8579         }
8580
8581         status = winreg_printer_addform1(p->mem_ctx, b,
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, b,
8596                                                         lp_const_servicename(snum));
8597                 if (!W_ERROR_IS_OK(status)) {
8598                         return status;
8599                 }
8600         }
8601
8602         return status;
8603 }
8604
8605 /****************************************************************
8606  _spoolss_DeleteForm
8607 ****************************************************************/
8608
8609 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8610                            struct spoolss_DeleteForm *r)
8611 {
8612         const char *form_name = r->in.form_name;
8613         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8614         int snum = -1;
8615         WERROR status = WERR_OK;
8616         struct dcerpc_binding_handle *b;
8617
8618         DEBUG(5,("_spoolss_DeleteForm\n"));
8619
8620         if (!Printer) {
8621                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8622                         OUR_HANDLE(r->in.handle)));
8623                 return WERR_BADFID;
8624         }
8625
8626         if ((p->session_info->utok.uid != sec_initial_uid()) &&
8627             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8628             !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8629                                           p->session_info->info3->base.domain.string,
8630                                           NULL,
8631                                           p->session_info->security_token,
8632                                           lp_printer_admin(snum))) {
8633                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8634                 return WERR_ACCESS_DENIED;
8635         }
8636
8637         status = winreg_printer_binding_handle(p->mem_ctx,
8638                                                get_session_info_system(),
8639                                                p->msg_ctx,
8640                                                &b);
8641         if (!W_ERROR_IS_OK(status)) {
8642                 return status;
8643         }
8644
8645         status = winreg_printer_deleteform1(p->mem_ctx, b,
8646                                             form_name);
8647         if (!W_ERROR_IS_OK(status)) {
8648                 return status;
8649         }
8650
8651         /*
8652          * ChangeID must always be set if this is a printer
8653          */
8654         if (Printer->printer_type == SPLHND_PRINTER) {
8655                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8656                         return WERR_BADFID;
8657                 }
8658
8659                 status = winreg_printer_update_changeid(p->mem_ctx, b,
8660                                                         lp_const_servicename(snum));
8661                 if (!W_ERROR_IS_OK(status)) {
8662                         return status;
8663                 }
8664         }
8665
8666         return status;
8667 }
8668
8669 /****************************************************************
8670  _spoolss_SetForm
8671 ****************************************************************/
8672
8673 WERROR _spoolss_SetForm(struct pipes_struct *p,
8674                         struct spoolss_SetForm *r)
8675 {
8676         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8677         const char *form_name = r->in.form_name;
8678         int snum = -1;
8679         WERROR status = WERR_OK;
8680         struct dcerpc_binding_handle *b;
8681
8682         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8683
8684         DEBUG(5,("_spoolss_SetForm\n"));
8685
8686         if (!Printer) {
8687                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8688                         OUR_HANDLE(r->in.handle)));
8689                 return WERR_BADFID;
8690         }
8691
8692         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8693            and not a printer admin, then fail */
8694
8695         if ((p->session_info->utok.uid != sec_initial_uid()) &&
8696              !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8697              !token_contains_name_in_list(uidtoname(p->session_info->utok.uid),
8698                                           p->session_info->info3->base.domain.string,
8699                                           NULL,
8700                                           p->session_info->security_token,
8701                                           lp_printer_admin(snum))) {
8702                 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8703                 return WERR_ACCESS_DENIED;
8704         }
8705
8706         status = winreg_printer_binding_handle(p->mem_ctx,
8707                                                get_session_info_system(),
8708                                                p->msg_ctx,
8709                                                &b);
8710         if (!W_ERROR_IS_OK(status)) {
8711                 return status;
8712         }
8713
8714         status = winreg_printer_setform1(p->mem_ctx, b,
8715                                          form_name,
8716                                          form);
8717         if (!W_ERROR_IS_OK(status)) {
8718                 return status;
8719         }
8720
8721         /*
8722          * ChangeID must always be set if this is a printer
8723          */
8724         if (Printer->printer_type == SPLHND_PRINTER) {
8725                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8726                         return WERR_BADFID;
8727                 }
8728
8729                 status = winreg_printer_update_changeid(p->mem_ctx, b,
8730                                                         lp_const_servicename(snum));
8731                 if (!W_ERROR_IS_OK(status)) {
8732                         return status;
8733                 }
8734         }
8735
8736         return status;
8737 }
8738
8739 /****************************************************************************
8740  fill_print_processor1
8741 ****************************************************************************/
8742
8743 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8744                                     struct spoolss_PrintProcessorInfo1 *r,
8745                                     const char *print_processor_name)
8746 {
8747         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8748         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8749
8750         return WERR_OK;
8751 }
8752
8753 /****************************************************************************
8754  enumprintprocessors level 1.
8755 ****************************************************************************/
8756
8757 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8758                                           union spoolss_PrintProcessorInfo **info_p,
8759                                           uint32_t *count)
8760 {
8761         union spoolss_PrintProcessorInfo *info;
8762         WERROR result;
8763
8764         info = talloc_array(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8765         W_ERROR_HAVE_NO_MEMORY(info);
8766
8767         *count = 1;
8768
8769         result = fill_print_processor1(info, &info[0].info1, "winprint");
8770         if (!W_ERROR_IS_OK(result)) {
8771                 goto out;
8772         }
8773
8774  out:
8775         if (!W_ERROR_IS_OK(result)) {
8776                 TALLOC_FREE(info);
8777                 *count = 0;
8778                 return result;
8779         }
8780
8781         *info_p = info;
8782
8783         return WERR_OK;
8784 }
8785
8786 /****************************************************************
8787  _spoolss_EnumPrintProcessors
8788 ****************************************************************/
8789
8790 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
8791                                     struct spoolss_EnumPrintProcessors *r)
8792 {
8793         WERROR result;
8794
8795         /* that's an [in out] buffer */
8796
8797         if (!r->in.buffer && (r->in.offered != 0)) {
8798                 return WERR_INVALID_PARAM;
8799         }
8800
8801         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8802
8803         /*
8804          * Enumerate the print processors ...
8805          *
8806          * Just reply with "winprint", to keep NT happy
8807          * and I can use my nice printer checker.
8808          */
8809
8810         *r->out.count = 0;
8811         *r->out.needed = 0;
8812         *r->out.info = NULL;
8813
8814         if (!get_short_archi(r->in.environment)) {
8815                 return WERR_INVALID_ENVIRONMENT;
8816         }
8817
8818         switch (r->in.level) {
8819         case 1:
8820                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8821                                                      r->out.count);
8822                 break;
8823         default:
8824                 return WERR_UNKNOWN_LEVEL;
8825         }
8826
8827         if (!W_ERROR_IS_OK(result)) {
8828                 return result;
8829         }
8830
8831         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8832                                                      spoolss_EnumPrintProcessors,
8833                                                      *r->out.info, r->in.level,
8834                                                      *r->out.count);
8835         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8836         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8837
8838         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8839 }
8840
8841 /****************************************************************************
8842  fill_printprocdatatype1
8843 ****************************************************************************/
8844
8845 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8846                                       struct spoolss_PrintProcDataTypesInfo1 *r,
8847                                       const char *name_array)
8848 {
8849         r->name_array = talloc_strdup(mem_ctx, name_array);
8850         W_ERROR_HAVE_NO_MEMORY(r->name_array);
8851
8852         return WERR_OK;
8853 }
8854
8855 /****************************************************************************
8856  enumprintprocdatatypes level 1.
8857 ****************************************************************************/
8858
8859 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8860                                              union spoolss_PrintProcDataTypesInfo **info_p,
8861                                              uint32_t *count)
8862 {
8863         WERROR result;
8864         union spoolss_PrintProcDataTypesInfo *info;
8865
8866         info = talloc_array(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8867         W_ERROR_HAVE_NO_MEMORY(info);
8868
8869         *count = 1;
8870
8871         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8872         if (!W_ERROR_IS_OK(result)) {
8873                 goto out;
8874         }
8875
8876  out:
8877         if (!W_ERROR_IS_OK(result)) {
8878                 TALLOC_FREE(info);
8879                 *count = 0;
8880                 return result;
8881         }
8882
8883         *info_p = info;
8884
8885         return WERR_OK;
8886 }
8887
8888 /****************************************************************
8889  _spoolss_EnumPrintProcDataTypes
8890 ****************************************************************/
8891
8892 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
8893                                        struct spoolss_EnumPrintProcDataTypes *r)
8894 {
8895         WERROR result;
8896
8897         /* that's an [in out] buffer */
8898
8899         if (!r->in.buffer && (r->in.offered != 0)) {
8900                 return WERR_INVALID_PARAM;
8901         }
8902
8903         DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8904
8905         *r->out.count = 0;
8906         *r->out.needed = 0;
8907         *r->out.info = NULL;
8908
8909         if (r->in.print_processor_name == NULL ||
8910             !strequal(r->in.print_processor_name, "winprint")) {
8911                 return WERR_UNKNOWN_PRINTPROCESSOR;
8912         }
8913
8914         switch (r->in.level) {
8915         case 1:
8916                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8917                                                         r->out.count);
8918                 break;
8919         default:
8920                 return WERR_UNKNOWN_LEVEL;
8921         }
8922
8923         if (!W_ERROR_IS_OK(result)) {
8924                 return result;
8925         }
8926
8927         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8928                                                      spoolss_EnumPrintProcDataTypes,
8929                                                      *r->out.info, r->in.level,
8930                                                      *r->out.count);
8931         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8932         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8933
8934         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8935 }
8936
8937 /****************************************************************************
8938  fill_monitor_1
8939 ****************************************************************************/
8940
8941 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8942                              struct spoolss_MonitorInfo1 *r,
8943                              const char *monitor_name)
8944 {
8945         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8946         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8947
8948         return WERR_OK;
8949 }
8950
8951 /****************************************************************************
8952  fill_monitor_2
8953 ****************************************************************************/
8954
8955 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8956                              struct spoolss_MonitorInfo2 *r,
8957                              const char *monitor_name,
8958                              const char *environment,
8959                              const char *dll_name)
8960 {
8961         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8962         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8963         r->environment                  = talloc_strdup(mem_ctx, environment);
8964         W_ERROR_HAVE_NO_MEMORY(r->environment);
8965         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
8966         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
8967
8968         return WERR_OK;
8969 }
8970
8971 /****************************************************************************
8972  enumprintmonitors level 1.
8973 ****************************************************************************/
8974
8975 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
8976                                         union spoolss_MonitorInfo **info_p,
8977                                         uint32_t *count)
8978 {
8979         union spoolss_MonitorInfo *info;
8980         WERROR result = WERR_OK;
8981
8982         info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
8983         W_ERROR_HAVE_NO_MEMORY(info);
8984
8985         *count = 2;
8986
8987         result = fill_monitor_1(info, &info[0].info1,
8988                                 SPL_LOCAL_PORT);
8989         if (!W_ERROR_IS_OK(result)) {
8990                 goto out;
8991         }
8992
8993         result = fill_monitor_1(info, &info[1].info1,
8994                                 SPL_TCPIP_PORT);
8995         if (!W_ERROR_IS_OK(result)) {
8996                 goto out;
8997         }
8998
8999 out:
9000         if (!W_ERROR_IS_OK(result)) {
9001                 TALLOC_FREE(info);
9002                 *count = 0;
9003                 return result;
9004         }
9005
9006         *info_p = info;
9007
9008         return WERR_OK;
9009 }
9010
9011 /****************************************************************************
9012  enumprintmonitors level 2.
9013 ****************************************************************************/
9014
9015 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
9016                                         union spoolss_MonitorInfo **info_p,
9017                                         uint32_t *count)
9018 {
9019         union spoolss_MonitorInfo *info;
9020         WERROR result = WERR_OK;
9021
9022         info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9023         W_ERROR_HAVE_NO_MEMORY(info);
9024
9025         *count = 2;
9026
9027         result = fill_monitor_2(info, &info[0].info2,
9028                                 SPL_LOCAL_PORT,
9029                                 "Windows NT X86", /* FIXME */
9030                                 "localmon.dll");
9031         if (!W_ERROR_IS_OK(result)) {
9032                 goto out;
9033         }
9034
9035         result = fill_monitor_2(info, &info[1].info2,
9036                                 SPL_TCPIP_PORT,
9037                                 "Windows NT X86", /* FIXME */
9038                                 "tcpmon.dll");
9039         if (!W_ERROR_IS_OK(result)) {
9040                 goto out;
9041         }
9042
9043 out:
9044         if (!W_ERROR_IS_OK(result)) {
9045                 TALLOC_FREE(info);
9046                 *count = 0;
9047                 return result;
9048         }
9049
9050         *info_p = info;
9051
9052         return WERR_OK;
9053 }
9054
9055 /****************************************************************
9056  _spoolss_EnumMonitors
9057 ****************************************************************/
9058
9059 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
9060                              struct spoolss_EnumMonitors *r)
9061 {
9062         WERROR result;
9063
9064         /* that's an [in out] buffer */
9065
9066         if (!r->in.buffer && (r->in.offered != 0)) {
9067                 return WERR_INVALID_PARAM;
9068         }
9069
9070         DEBUG(5,("_spoolss_EnumMonitors\n"));
9071
9072         /*
9073          * Enumerate the print monitors ...
9074          *
9075          * Just reply with "Local Port", to keep NT happy
9076          * and I can use my nice printer checker.
9077          */
9078
9079         *r->out.count = 0;
9080         *r->out.needed = 0;
9081         *r->out.info = NULL;
9082
9083         switch (r->in.level) {
9084         case 1:
9085                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
9086                                                    r->out.count);
9087                 break;
9088         case 2:
9089                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
9090                                                    r->out.count);
9091                 break;
9092         default:
9093                 return WERR_UNKNOWN_LEVEL;
9094         }
9095
9096         if (!W_ERROR_IS_OK(result)) {
9097                 return result;
9098         }
9099
9100         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9101                                                      spoolss_EnumMonitors,
9102                                                      *r->out.info, r->in.level,
9103                                                      *r->out.count);
9104         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9105         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9106
9107         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9108 }
9109
9110 /****************************************************************************
9111 ****************************************************************************/
9112
9113 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
9114                              const print_queue_struct *queue,
9115                              int count, int snum,
9116                              struct spoolss_PrinterInfo2 *pinfo2,
9117                              uint32_t jobid,
9118                              struct spoolss_JobInfo1 *r)
9119 {
9120         int i = 0;
9121         bool found = false;
9122
9123         for (i=0; i<count; i++) {
9124                 if (queue[i].job == (int)jobid) {
9125                         found = true;
9126                         break;
9127                 }
9128         }
9129
9130         if (found == false) {
9131                 /* NT treats not found as bad param... yet another bad choice */
9132                 return WERR_INVALID_PARAM;
9133         }
9134
9135         return fill_job_info1(mem_ctx,
9136                               r,
9137                               &queue[i],
9138                               i,
9139                               snum,
9140                               pinfo2);
9141 }
9142
9143 /****************************************************************************
9144 ****************************************************************************/
9145
9146 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9147                              const print_queue_struct *queue,
9148                              int count, int snum,
9149                              struct spoolss_PrinterInfo2 *pinfo2,
9150                              uint32_t jobid,
9151                              struct spoolss_JobInfo2 *r)
9152 {
9153         int i = 0;
9154         bool found = false;
9155         struct spoolss_DeviceMode *devmode;
9156         WERROR result;
9157
9158         for (i=0; i<count; i++) {
9159                 if (queue[i].job == (int)jobid) {
9160                         found = true;
9161                         break;
9162                 }
9163         }
9164
9165         if (found == false) {
9166                 /* NT treats not found as bad param... yet another bad
9167                    choice */
9168                 return WERR_INVALID_PARAM;
9169         }
9170
9171         /*
9172          * if the print job does not have a DEVMODE associated with it,
9173          * just use the one for the printer. A NULL devicemode is not
9174          *  a failure condition
9175          */
9176
9177         devmode = print_job_devmode(lp_const_servicename(snum), jobid);
9178         if (!devmode) {
9179                 result = spoolss_create_default_devmode(mem_ctx,
9180                                                 pinfo2->printername,
9181                                                 &devmode);
9182                 if (!W_ERROR_IS_OK(result)) {
9183                         DEBUG(3, ("Can't proceed w/o a devmode!"));
9184                         return result;
9185                 }
9186         }
9187
9188         return fill_job_info2(mem_ctx,
9189                               r,
9190                               &queue[i],
9191                               i,
9192                               snum,
9193                               pinfo2,
9194                               devmode);
9195 }
9196
9197 /****************************************************************
9198  _spoolss_GetJob
9199 ****************************************************************/
9200
9201 WERROR _spoolss_GetJob(struct pipes_struct *p,
9202                        struct spoolss_GetJob *r)
9203 {
9204         WERROR result = WERR_OK;
9205         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9206         int snum;
9207         int count;
9208         print_queue_struct      *queue = NULL;
9209         print_status_struct prt_status;
9210
9211         /* that's an [in out] buffer */
9212
9213         if (!r->in.buffer && (r->in.offered != 0)) {
9214                 return WERR_INVALID_PARAM;
9215         }
9216
9217         DEBUG(5,("_spoolss_GetJob\n"));
9218
9219         *r->out.needed = 0;
9220
9221         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9222                 return WERR_BADFID;
9223         }
9224
9225         result = winreg_get_printer_internal(p->mem_ctx,
9226                                     get_session_info_system(),
9227                                     p->msg_ctx,
9228                                     lp_const_servicename(snum),
9229                                     &pinfo2);
9230         if (!W_ERROR_IS_OK(result)) {
9231                 return result;
9232         }
9233
9234         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9235
9236         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9237                      count, prt_status.status, prt_status.message));
9238
9239         switch (r->in.level) {
9240         case 1:
9241                 result = getjob_level_1(p->mem_ctx,
9242                                         queue, count, snum, pinfo2,
9243                                         r->in.job_id, &r->out.info->info1);
9244                 break;
9245         case 2:
9246                 result = getjob_level_2(p->mem_ctx,
9247                                         queue, count, snum, pinfo2,
9248                                         r->in.job_id, &r->out.info->info2);
9249                 break;
9250         default:
9251                 result = WERR_UNKNOWN_LEVEL;
9252                 break;
9253         }
9254
9255         SAFE_FREE(queue);
9256         TALLOC_FREE(pinfo2);
9257
9258         if (!W_ERROR_IS_OK(result)) {
9259                 TALLOC_FREE(r->out.info);
9260                 return result;
9261         }
9262
9263         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9264                                                                                    r->in.level);
9265         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9266
9267         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9268 }
9269
9270 /****************************************************************
9271  _spoolss_GetPrinterDataEx
9272 ****************************************************************/
9273
9274 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9275                                  struct spoolss_GetPrinterDataEx *r)
9276 {
9277
9278         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9279         const char *printer;
9280         int                     snum = 0;
9281         WERROR result = WERR_OK;
9282         DATA_BLOB blob;
9283         enum winreg_Type val_type = REG_NONE;
9284         uint8_t *val_data = NULL;
9285         uint32_t val_size = 0;
9286         struct dcerpc_binding_handle *b;
9287
9288         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9289
9290         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9291                 r->in.key_name, r->in.value_name));
9292
9293         /* in case of problem, return some default values */
9294
9295         *r->out.needed  = 0;
9296         *r->out.type    = REG_NONE;
9297
9298         if (!Printer) {
9299                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9300                         OUR_HANDLE(r->in.handle)));
9301                 result = WERR_BADFID;
9302                 goto done;
9303         }
9304
9305         /* Is the handle to a printer or to the server? */
9306
9307         if (Printer->printer_type == SPLHND_SERVER) {
9308
9309                 union spoolss_PrinterData data;
9310
9311                 result = getprinterdata_printer_server(p->mem_ctx,
9312                                                        r->in.value_name,
9313                                                        r->out.type,
9314                                                        &data);
9315                 if (!W_ERROR_IS_OK(result)) {
9316                         return result;
9317                 }
9318
9319                 result = push_spoolss_PrinterData(p->mem_ctx, &blob,
9320                                                   *r->out.type, &data);
9321                 if (!W_ERROR_IS_OK(result)) {
9322                         return result;
9323                 }
9324
9325                 *r->out.needed = blob.length;
9326
9327                 if (r->in.offered >= *r->out.needed) {
9328                         memcpy(r->out.data, blob.data, blob.length);
9329                 }
9330
9331                 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9332         }
9333
9334         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9335                 return WERR_BADFID;
9336         }
9337         printer = lp_const_servicename(snum);
9338
9339         /* check to see if the keyname is valid */
9340         if (!strlen(r->in.key_name)) {
9341                 return WERR_INVALID_PARAM;
9342         }
9343
9344         result = winreg_printer_binding_handle(p->mem_ctx,
9345                                                get_session_info_system(),
9346                                                p->msg_ctx,
9347                                                &b);
9348         if (!W_ERROR_IS_OK(result)) {
9349                 return result;
9350         }
9351
9352         /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9353         if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9354             strequal(r->in.value_name, "ChangeId")) {
9355                 *r->out.type = REG_DWORD;
9356                 *r->out.needed = 4;
9357                 if (r->in.offered >= *r->out.needed) {
9358                         uint32_t changeid = 0;
9359
9360                         result = winreg_printer_get_changeid(p->mem_ctx, b,
9361                                                              printer,
9362                                                              &changeid);
9363                         if (!W_ERROR_IS_OK(result)) {
9364                                 return result;
9365                         }
9366
9367                         SIVAL(r->out.data, 0, changeid);
9368                         result = WERR_OK;
9369                 }
9370                 goto done;
9371         }
9372
9373         result = winreg_get_printer_dataex(p->mem_ctx, b,
9374                                            printer,
9375                                            r->in.key_name,
9376                                            r->in.value_name,
9377                                            &val_type,
9378                                            &val_data,
9379                                            &val_size);
9380         if (!W_ERROR_IS_OK(result)) {
9381                 return result;
9382         }
9383
9384         *r->out.needed = val_size;
9385         *r->out.type = val_type;
9386
9387         if (r->in.offered >= *r->out.needed) {
9388                 memcpy(r->out.data, val_data, val_size);
9389         }
9390
9391  done:
9392         /* retain type when returning WERR_MORE_DATA */
9393         r->out.data     = SPOOLSS_BUFFER_OK(r->out.data, r->out.data);
9394
9395         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9396 }
9397
9398 /****************************************************************
9399  _spoolss_SetPrinterDataEx
9400 ****************************************************************/
9401
9402 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9403                                  struct spoolss_SetPrinterDataEx *r)
9404 {
9405         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9406         int                     snum = 0;
9407         WERROR                  result = WERR_OK;
9408         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9409         char                    *oid_string;
9410         struct dcerpc_binding_handle *b;
9411
9412         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9413
9414         /* From MSDN documentation of SetPrinterDataEx: pass request to
9415            SetPrinterData if key is "PrinterDriverData" */
9416
9417         if (!Printer) {
9418                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9419                         OUR_HANDLE(r->in.handle)));
9420                 return WERR_BADFID;
9421         }
9422
9423         if (Printer->printer_type == SPLHND_SERVER) {
9424                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9425                         "Not implemented for server handles yet\n"));
9426                 return WERR_INVALID_PARAM;
9427         }
9428
9429         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9430                 return WERR_BADFID;
9431         }
9432
9433         /*
9434          * Access check : NT returns "access denied" if you make a
9435          * SetPrinterData call without the necessary privildge.
9436          * we were originally returning OK if nothing changed
9437          * which made Win2k issue **a lot** of SetPrinterData
9438          * when connecting to a printer  --jerry
9439          */
9440
9441         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9442                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9443                         "change denied by handle access permissions\n"));
9444                 return WERR_ACCESS_DENIED;
9445         }
9446
9447         result = winreg_printer_binding_handle(p->mem_ctx,
9448                                                get_session_info_system(),
9449                                                p->msg_ctx,
9450                                                &b);
9451         if (!W_ERROR_IS_OK(result)) {
9452                 return result;
9453         }
9454
9455         result = winreg_get_printer(Printer, b,
9456                                     lp_servicename(snum),
9457                                     &pinfo2);
9458         if (!W_ERROR_IS_OK(result)) {
9459                 return result;
9460         }
9461
9462         /* check for OID in valuename */
9463
9464         oid_string = strchr(r->in.value_name, ',');
9465         if (oid_string) {
9466                 *oid_string = '\0';
9467                 oid_string++;
9468         }
9469
9470         /* save the registry data */
9471
9472         result = winreg_set_printer_dataex(p->mem_ctx, b,
9473                                            pinfo2->sharename,
9474                                            r->in.key_name,
9475                                            r->in.value_name,
9476                                            r->in.type,
9477                                            r->in.data,
9478                                            r->in.offered);
9479
9480         if (W_ERROR_IS_OK(result)) {
9481                 /* save the OID if one was specified */
9482                 if (oid_string) {
9483                         char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
9484                                 r->in.key_name, SPOOL_OID_KEY);
9485                         if (!str) {
9486                                 result = WERR_NOMEM;
9487                                 goto done;
9488                         }
9489
9490                         /*
9491                          * I'm not checking the status here on purpose.  Don't know
9492                          * if this is right, but I'm returning the status from the
9493                          * previous set_printer_dataex() call.  I have no idea if
9494                          * this is right.    --jerry
9495                          */
9496                         winreg_set_printer_dataex(p->mem_ctx, b,
9497                                                   pinfo2->sharename,
9498                                                   str,
9499                                                   r->in.value_name,
9500                                                   REG_SZ,
9501                                                   (uint8_t *) oid_string,
9502                                                   strlen(oid_string) + 1);
9503                 }
9504
9505                 result = winreg_printer_update_changeid(p->mem_ctx, b,
9506                                                         lp_const_servicename(snum));
9507
9508         }
9509
9510 done:
9511         talloc_free(pinfo2);
9512         return result;
9513 }
9514
9515 /****************************************************************
9516  _spoolss_DeletePrinterDataEx
9517 ****************************************************************/
9518
9519 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9520                                     struct spoolss_DeletePrinterDataEx *r)
9521 {
9522         const char *printer;
9523         int             snum=0;
9524         WERROR          status = WERR_OK;
9525         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9526
9527         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9528
9529         if (!Printer) {
9530                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9531                         "Invalid handle (%s:%u:%u).\n",
9532                         OUR_HANDLE(r->in.handle)));
9533                 return WERR_BADFID;
9534         }
9535
9536         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9537                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9538                         "printer properties change denied by handle\n"));
9539                 return WERR_ACCESS_DENIED;
9540         }
9541
9542         if (!r->in.value_name || !r->in.key_name) {
9543                 return WERR_NOMEM;
9544         }
9545
9546         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9547                 return WERR_BADFID;
9548         }
9549         printer = lp_const_servicename(snum);
9550
9551         status = winreg_delete_printer_dataex_internal(p->mem_ctx,
9552                                               get_session_info_system(),
9553                                               p->msg_ctx,
9554                                               printer,
9555                                               r->in.key_name,
9556                                               r->in.value_name);
9557         if (W_ERROR_IS_OK(status)) {
9558                 status = winreg_printer_update_changeid_internal(p->mem_ctx,
9559                                                         get_session_info_system(),
9560                                                         p->msg_ctx,
9561                                                         printer);
9562         }
9563
9564         return status;
9565 }
9566
9567 /****************************************************************
9568  _spoolss_EnumPrinterKey
9569 ****************************************************************/
9570
9571 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9572                                struct spoolss_EnumPrinterKey *r)
9573 {
9574         uint32_t        num_keys;
9575         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9576         int             snum = 0;
9577         WERROR          result = WERR_BADFILE;
9578         const char **array = NULL;
9579         DATA_BLOB blob;
9580
9581         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9582
9583         if (!Printer) {
9584                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9585                         OUR_HANDLE(r->in.handle)));
9586                 return WERR_BADFID;
9587         }
9588
9589         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9590                 return WERR_BADFID;
9591         }
9592
9593         result = winreg_enum_printer_key_internal(p->mem_ctx,
9594                                          get_session_info_system(),
9595                                          p->msg_ctx,
9596                                          lp_const_servicename(snum),
9597                                          r->in.key_name,
9598                                          &num_keys,
9599                                          &array);
9600         if (!W_ERROR_IS_OK(result)) {
9601                 goto done;
9602         }
9603
9604         if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9605                 result = WERR_NOMEM;
9606                 goto done;
9607         }
9608
9609         *r->out._ndr_size = r->in.offered / 2;
9610         *r->out.needed = blob.length;
9611
9612         if (r->in.offered < *r->out.needed) {
9613                 result = WERR_MORE_DATA;
9614         } else {
9615                 result = WERR_OK;
9616                 r->out.key_buffer->string_array = array;
9617         }
9618
9619  done:
9620         if (!W_ERROR_IS_OK(result)) {
9621                 TALLOC_FREE(array);
9622                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9623                         *r->out.needed = 0;
9624                 }
9625         }
9626
9627         return result;
9628 }
9629
9630 /****************************************************************
9631  _spoolss_DeletePrinterKey
9632 ****************************************************************/
9633
9634 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9635                                  struct spoolss_DeletePrinterKey *r)
9636 {
9637         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9638         int                     snum=0;
9639         WERROR                  status;
9640         const char *printer;
9641         struct dcerpc_binding_handle *b;
9642
9643         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9644
9645         if (!Printer) {
9646                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9647                         OUR_HANDLE(r->in.handle)));
9648                 return WERR_BADFID;
9649         }
9650
9651         /* if keyname == NULL, return error */
9652         if ( !r->in.key_name )
9653                 return WERR_INVALID_PARAM;
9654
9655         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9656                 return WERR_BADFID;
9657         }
9658
9659         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9660                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9661                         "printer properties change denied by handle\n"));
9662                 return WERR_ACCESS_DENIED;
9663         }
9664
9665         printer = lp_const_servicename(snum);
9666
9667         status = winreg_printer_binding_handle(p->mem_ctx,
9668                                                get_session_info_system(),
9669                                                p->msg_ctx,
9670                                                &b);
9671         if (!W_ERROR_IS_OK(status)) {
9672                 return status;
9673         }
9674
9675         /* delete the key and all subkeys */
9676         status = winreg_delete_printer_key(p->mem_ctx, b,
9677                                            printer,
9678                                            r->in.key_name);
9679         if (W_ERROR_IS_OK(status)) {
9680                 status = winreg_printer_update_changeid(p->mem_ctx, b,
9681                                                         printer);
9682         }
9683
9684         return status;
9685 }
9686
9687 /****************************************************************
9688  _spoolss_EnumPrinterDataEx
9689 ****************************************************************/
9690
9691 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
9692                                   struct spoolss_EnumPrinterDataEx *r)
9693 {
9694         uint32_t        count = 0;
9695         struct spoolss_PrinterEnumValues *info = NULL;
9696         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9697         int             snum;
9698         WERROR          result;
9699
9700         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9701
9702         *r->out.count = 0;
9703         *r->out.needed = 0;
9704         *r->out.info = NULL;
9705
9706         if (!Printer) {
9707                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9708                         OUR_HANDLE(r->in.handle)));
9709                 return WERR_BADFID;
9710         }
9711
9712         /*
9713          * first check for a keyname of NULL or "".  Win2k seems to send
9714          * this a lot and we should send back WERR_INVALID_PARAM
9715          * no need to spend time looking up the printer in this case.
9716          * --jerry
9717          */
9718
9719         if (!strlen(r->in.key_name)) {
9720                 result = WERR_INVALID_PARAM;
9721                 goto done;
9722         }
9723
9724         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9725                 return WERR_BADFID;
9726         }
9727
9728         /* now look for a match on the key name */
9729         result = winreg_enum_printer_dataex_internal(p->mem_ctx,
9730                                             get_session_info_system(),
9731                                             p->msg_ctx,
9732                                             lp_const_servicename(snum),
9733                                             r->in.key_name,
9734                                             &count,
9735                                             &info);
9736         if (!W_ERROR_IS_OK(result)) {
9737                 goto done;
9738         }
9739
9740 #if 0 /* FIXME - gd */
9741         /* housekeeping information in the reply */
9742
9743         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9744          * the hand marshalled container size is a multiple
9745          * of 4 bytes for RPC alignment.
9746          */
9747
9748         if (needed % 4) {
9749                 needed += 4-(needed % 4);
9750         }
9751 #endif
9752         *r->out.count   = count;
9753         *r->out.info    = info;
9754
9755  done:
9756         if (!W_ERROR_IS_OK(result)) {
9757                 return result;
9758         }
9759
9760         *r->out.needed  = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9761                                                spoolss_EnumPrinterDataEx,
9762                                                *r->out.info,
9763                                                *r->out.count);
9764         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9765         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9766
9767         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9768 }
9769
9770 /****************************************************************************
9771 ****************************************************************************/
9772
9773 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9774                                                  const char *servername,
9775                                                  const char *environment,
9776                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
9777 {
9778         WERROR werr;
9779         char *path = NULL;
9780
9781         werr = compose_spoolss_server_path(mem_ctx,
9782                                            servername,
9783                                            environment,
9784                                            SPOOLSS_PRTPROCS_PATH,
9785                                            &path);
9786         if (!W_ERROR_IS_OK(werr)) {
9787                 return werr;
9788         }
9789
9790         DEBUG(4,("print processor directory: [%s]\n", path));
9791
9792         r->directory_name = path;
9793
9794         return WERR_OK;
9795 }
9796
9797 /****************************************************************
9798  _spoolss_GetPrintProcessorDirectory
9799 ****************************************************************/
9800
9801 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
9802                                            struct spoolss_GetPrintProcessorDirectory *r)
9803 {
9804         WERROR result;
9805         char *prnproc_share = NULL;
9806         bool prnproc_share_exists = false;
9807         int snum;
9808
9809         /* that's an [in out] buffer */
9810
9811         if (!r->in.buffer && (r->in.offered != 0)) {
9812                 return WERR_INVALID_PARAM;
9813         }
9814
9815         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9816                 r->in.level));
9817
9818         *r->out.needed = 0;
9819
9820         /* r->in.level is ignored */
9821
9822         /* We always should reply with a local print processor directory so that
9823          * users are not forced to have a [prnproc$] share on the Samba spoolss
9824          * server, if users decide to do so, lets announce it though - Guenther */
9825
9826         snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
9827         if (!prnproc_share) {
9828                 return WERR_NOMEM;
9829         }
9830         if (snum != -1) {
9831                 prnproc_share_exists = true;
9832         }
9833
9834         result = getprintprocessordirectory_level_1(p->mem_ctx,
9835                                                     prnproc_share_exists ? r->in.server : NULL,
9836                                                     r->in.environment,
9837                                                     &r->out.info->info1);
9838         if (!W_ERROR_IS_OK(result)) {
9839                 TALLOC_FREE(r->out.info);
9840                 return result;
9841         }
9842
9843         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
9844                                                                                    r->out.info, r->in.level);
9845         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9846
9847         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9848 }
9849
9850 /*******************************************************************
9851  ********************************************************************/
9852
9853 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9854                                const char *dllname)
9855 {
9856         enum ndr_err_code ndr_err;
9857         struct spoolss_MonitorUi ui;
9858
9859         ui.dll_name = dllname;
9860
9861         ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
9862                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9863         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9864                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9865         }
9866         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9867 }
9868
9869 /*******************************************************************
9870  Streams the monitor UI DLL name in UNICODE
9871 *******************************************************************/
9872
9873 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9874                                struct security_token *token, DATA_BLOB *in,
9875                                DATA_BLOB *out, uint32_t *needed)
9876 {
9877         const char *dllname = "tcpmonui.dll";
9878
9879         *needed = (strlen(dllname)+1) * 2;
9880
9881         if (out->length < *needed) {
9882                 return WERR_INSUFFICIENT_BUFFER;
9883         }
9884
9885         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9886                 return WERR_NOMEM;
9887         }
9888
9889         return WERR_OK;
9890 }
9891
9892 /*******************************************************************
9893  ********************************************************************/
9894
9895 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9896                              struct spoolss_PortData1 *port1,
9897                              const DATA_BLOB *buf)
9898 {
9899         enum ndr_err_code ndr_err;
9900         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
9901                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9902         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9903                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9904         }
9905         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9906 }
9907
9908 /*******************************************************************
9909  ********************************************************************/
9910
9911 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9912                              struct spoolss_PortData2 *port2,
9913                              const DATA_BLOB *buf)
9914 {
9915         enum ndr_err_code ndr_err;
9916         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
9917                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9918         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9919                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9920         }
9921         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9922 }
9923
9924 /*******************************************************************
9925  Create a new TCP/IP port
9926 *******************************************************************/
9927
9928 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9929                              struct security_token *token, DATA_BLOB *in,
9930                              DATA_BLOB *out, uint32_t *needed)
9931 {
9932         struct spoolss_PortData1 port1;
9933         struct spoolss_PortData2 port2;
9934         char *device_uri = NULL;
9935         uint32_t version;
9936
9937         const char *portname;
9938         const char *hostaddress;
9939         const char *queue;
9940         uint32_t port_number;
9941         uint32_t protocol;
9942
9943         /* peek for spoolss_PortData version */
9944
9945         if (!in || (in->length < (128 + 4))) {
9946                 return WERR_GENERAL_FAILURE;
9947         }
9948
9949         version = IVAL(in->data, 128);
9950
9951         switch (version) {
9952                 case 1:
9953                         ZERO_STRUCT(port1);
9954
9955                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
9956                                 return WERR_NOMEM;
9957                         }
9958
9959                         portname        = port1.portname;
9960                         hostaddress     = port1.hostaddress;
9961                         queue           = port1.queue;
9962                         protocol        = port1.protocol;
9963                         port_number     = port1.port_number;
9964
9965                         break;
9966                 case 2:
9967                         ZERO_STRUCT(port2);
9968
9969                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
9970                                 return WERR_NOMEM;
9971                         }
9972
9973                         portname        = port2.portname;
9974                         hostaddress     = port2.hostaddress;
9975                         queue           = port2.queue;
9976                         protocol        = port2.protocol;
9977                         port_number     = port2.port_number;
9978
9979                         break;
9980                 default:
9981                         DEBUG(1,("xcvtcp_addport: "
9982                                 "unknown version of port_data: %d\n", version));
9983                         return WERR_UNKNOWN_PORT;
9984         }
9985
9986         /* create the device URI and call the add_port_hook() */
9987
9988         switch (protocol) {
9989         case PROTOCOL_RAWTCP_TYPE:
9990                 device_uri = talloc_asprintf(mem_ctx,
9991                                 "socket://%s:%d/", hostaddress,
9992                                 port_number);
9993                 break;
9994
9995         case PROTOCOL_LPR_TYPE:
9996                 device_uri = talloc_asprintf(mem_ctx,
9997                         "lpr://%s/%s", hostaddress, queue );
9998                 break;
9999
10000         default:
10001                 return WERR_UNKNOWN_PORT;
10002         }
10003
10004         if (!device_uri) {
10005                 return WERR_NOMEM;
10006         }
10007
10008         return add_port_hook(mem_ctx, token, portname, device_uri);
10009 }
10010
10011 /*******************************************************************
10012 *******************************************************************/
10013
10014 struct xcv_api_table xcvtcp_cmds[] = {
10015         { "MonitorUI",  xcvtcp_monitorui },
10016         { "AddPort",    xcvtcp_addport},
10017         { NULL,         NULL }
10018 };
10019
10020 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
10021                                      struct security_token *token, const char *command,
10022                                      DATA_BLOB *inbuf,
10023                                      DATA_BLOB *outbuf,
10024                                      uint32_t *needed )
10025 {
10026         int i;
10027
10028         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
10029
10030         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
10031                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
10032                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10033         }
10034
10035         return WERR_BADFUNC;
10036 }
10037
10038 /*******************************************************************
10039 *******************************************************************/
10040 #if 0   /* don't support management using the "Local Port" monitor */
10041
10042 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
10043                                  struct security_token *token, DATA_BLOB *in,
10044                                  DATA_BLOB *out, uint32_t *needed)
10045 {
10046         const char *dllname = "localui.dll";
10047
10048         *needed = (strlen(dllname)+1) * 2;
10049
10050         if (out->length < *needed) {
10051                 return WERR_INSUFFICIENT_BUFFER;
10052         }
10053
10054         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10055                 return WERR_NOMEM;
10056         }
10057
10058         return WERR_OK;
10059 }
10060
10061 /*******************************************************************
10062 *******************************************************************/
10063
10064 struct xcv_api_table xcvlocal_cmds[] = {
10065         { "MonitorUI",  xcvlocal_monitorui },
10066         { NULL,         NULL }
10067 };
10068 #else
10069 struct xcv_api_table xcvlocal_cmds[] = {
10070         { NULL,         NULL }
10071 };
10072 #endif
10073
10074
10075
10076 /*******************************************************************
10077 *******************************************************************/
10078
10079 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
10080                                        struct security_token *token, const char *command,
10081                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
10082                                        uint32_t *needed)
10083 {
10084         int i;
10085
10086         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10087
10088         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10089                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10090                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10091         }
10092         return WERR_BADFUNC;
10093 }
10094
10095 /****************************************************************
10096  _spoolss_XcvData
10097 ****************************************************************/
10098
10099 WERROR _spoolss_XcvData(struct pipes_struct *p,
10100                         struct spoolss_XcvData *r)
10101 {
10102         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10103         DATA_BLOB out_data = data_blob_null;
10104         WERROR werror;
10105
10106         if (!Printer) {
10107                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10108                         OUR_HANDLE(r->in.handle)));
10109                 return WERR_BADFID;
10110         }
10111
10112         /* Has to be a handle to the TCP/IP port monitor */
10113
10114         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10115                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10116                 return WERR_BADFID;
10117         }
10118
10119         /* requires administrative access to the server */
10120
10121         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10122                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10123                 return WERR_ACCESS_DENIED;
10124         }
10125
10126         /* Allocate the outgoing buffer */
10127
10128         if (r->in.out_data_size) {
10129                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10130                 if (out_data.data == NULL) {
10131                         return WERR_NOMEM;
10132                 }
10133         }
10134
10135         switch ( Printer->printer_type ) {
10136         case SPLHND_PORTMON_TCP:
10137                 werror = process_xcvtcp_command(p->mem_ctx,
10138                                                 p->session_info->security_token,
10139                                                 r->in.function_name,
10140                                                 &r->in.in_data, &out_data,
10141                                                 r->out.needed);
10142                 break;
10143         case SPLHND_PORTMON_LOCAL:
10144                 werror = process_xcvlocal_command(p->mem_ctx,
10145                                                   p->session_info->security_token,
10146                                                   r->in.function_name,
10147                                                   &r->in.in_data, &out_data,
10148                                                   r->out.needed);
10149                 break;
10150         default:
10151                 werror = WERR_INVALID_PRINT_MONITOR;
10152         }
10153
10154         if (!W_ERROR_IS_OK(werror)) {
10155                 return werror;
10156         }
10157
10158         *r->out.status_code = 0;
10159
10160         if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10161                 memcpy(r->out.out_data, out_data.data,
10162                         MIN(r->in.out_data_size, out_data.length));
10163         }
10164
10165         return WERR_OK;
10166 }
10167
10168 /****************************************************************
10169  _spoolss_AddPrintProcessor
10170 ****************************************************************/
10171
10172 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10173                                   struct spoolss_AddPrintProcessor *r)
10174 {
10175         /* for now, just indicate success and ignore the add.  We'll
10176            automatically set the winprint processor for printer
10177            entries later.  Used to debug the LexMark Optra S 1855 PCL
10178            driver --jerry */
10179
10180         return WERR_OK;
10181 }
10182
10183 /****************************************************************
10184  _spoolss_AddPort
10185 ****************************************************************/
10186
10187 WERROR _spoolss_AddPort(struct pipes_struct *p,
10188                         struct spoolss_AddPort *r)
10189 {
10190         /* do what w2k3 does */
10191
10192         return WERR_NOT_SUPPORTED;
10193 }
10194
10195 /****************************************************************
10196  _spoolss_GetPrinterDriver
10197 ****************************************************************/
10198
10199 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10200                                  struct spoolss_GetPrinterDriver *r)
10201 {
10202         p->rng_fault_state = true;
10203         return WERR_NOT_SUPPORTED;
10204 }
10205
10206 /****************************************************************
10207  _spoolss_ReadPrinter
10208 ****************************************************************/
10209
10210 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10211                             struct spoolss_ReadPrinter *r)
10212 {
10213         p->rng_fault_state = true;
10214         return WERR_NOT_SUPPORTED;
10215 }
10216
10217 /****************************************************************
10218  _spoolss_WaitForPrinterChange
10219 ****************************************************************/
10220
10221 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10222                                      struct spoolss_WaitForPrinterChange *r)
10223 {
10224         p->rng_fault_state = true;
10225         return WERR_NOT_SUPPORTED;
10226 }
10227
10228 /****************************************************************
10229  _spoolss_ConfigurePort
10230 ****************************************************************/
10231
10232 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10233                               struct spoolss_ConfigurePort *r)
10234 {
10235         p->rng_fault_state = true;
10236         return WERR_NOT_SUPPORTED;
10237 }
10238
10239 /****************************************************************
10240  _spoolss_DeletePort
10241 ****************************************************************/
10242
10243 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10244                            struct spoolss_DeletePort *r)
10245 {
10246         p->rng_fault_state = true;
10247         return WERR_NOT_SUPPORTED;
10248 }
10249
10250 /****************************************************************
10251  _spoolss_CreatePrinterIC
10252 ****************************************************************/
10253
10254 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10255                                 struct spoolss_CreatePrinterIC *r)
10256 {
10257         p->rng_fault_state = true;
10258         return WERR_NOT_SUPPORTED;
10259 }
10260
10261 /****************************************************************
10262  _spoolss_PlayGDIScriptOnPrinterIC
10263 ****************************************************************/
10264
10265 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10266                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
10267 {
10268         p->rng_fault_state = true;
10269         return WERR_NOT_SUPPORTED;
10270 }
10271
10272 /****************************************************************
10273  _spoolss_DeletePrinterIC
10274 ****************************************************************/
10275
10276 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10277                                 struct spoolss_DeletePrinterIC *r)
10278 {
10279         p->rng_fault_state = true;
10280         return WERR_NOT_SUPPORTED;
10281 }
10282
10283 /****************************************************************
10284  _spoolss_AddPrinterConnection
10285 ****************************************************************/
10286
10287 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10288                                      struct spoolss_AddPrinterConnection *r)
10289 {
10290         p->rng_fault_state = true;
10291         return WERR_NOT_SUPPORTED;
10292 }
10293
10294 /****************************************************************
10295  _spoolss_DeletePrinterConnection
10296 ****************************************************************/
10297
10298 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10299                                         struct spoolss_DeletePrinterConnection *r)
10300 {
10301         p->rng_fault_state = true;
10302         return WERR_NOT_SUPPORTED;
10303 }
10304
10305 /****************************************************************
10306  _spoolss_PrinterMessageBox
10307 ****************************************************************/
10308
10309 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10310                                   struct spoolss_PrinterMessageBox *r)
10311 {
10312         p->rng_fault_state = true;
10313         return WERR_NOT_SUPPORTED;
10314 }
10315
10316 /****************************************************************
10317  _spoolss_AddMonitor
10318 ****************************************************************/
10319
10320 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10321                            struct spoolss_AddMonitor *r)
10322 {
10323         p->rng_fault_state = true;
10324         return WERR_NOT_SUPPORTED;
10325 }
10326
10327 /****************************************************************
10328  _spoolss_DeleteMonitor
10329 ****************************************************************/
10330
10331 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10332                               struct spoolss_DeleteMonitor *r)
10333 {
10334         p->rng_fault_state = true;
10335         return WERR_NOT_SUPPORTED;
10336 }
10337
10338 /****************************************************************
10339  _spoolss_DeletePrintProcessor
10340 ****************************************************************/
10341
10342 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10343                                      struct spoolss_DeletePrintProcessor *r)
10344 {
10345         p->rng_fault_state = true;
10346         return WERR_NOT_SUPPORTED;
10347 }
10348
10349 /****************************************************************
10350  _spoolss_AddPrintProvidor
10351 ****************************************************************/
10352
10353 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10354                                  struct spoolss_AddPrintProvidor *r)
10355 {
10356         p->rng_fault_state = true;
10357         return WERR_NOT_SUPPORTED;
10358 }
10359
10360 /****************************************************************
10361  _spoolss_DeletePrintProvidor
10362 ****************************************************************/
10363
10364 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10365                                     struct spoolss_DeletePrintProvidor *r)
10366 {
10367         p->rng_fault_state = true;
10368         return WERR_NOT_SUPPORTED;
10369 }
10370
10371 /****************************************************************
10372  _spoolss_FindFirstPrinterChangeNotification
10373 ****************************************************************/
10374
10375 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10376                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
10377 {
10378         p->rng_fault_state = true;
10379         return WERR_NOT_SUPPORTED;
10380 }
10381
10382 /****************************************************************
10383  _spoolss_FindNextPrinterChangeNotification
10384 ****************************************************************/
10385
10386 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10387                                                   struct spoolss_FindNextPrinterChangeNotification *r)
10388 {
10389         p->rng_fault_state = true;
10390         return WERR_NOT_SUPPORTED;
10391 }
10392
10393 /****************************************************************
10394  _spoolss_RouterFindFirstPrinterChangeNotificationOld
10395 ****************************************************************/
10396
10397 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10398                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10399 {
10400         p->rng_fault_state = true;
10401         return WERR_NOT_SUPPORTED;
10402 }
10403
10404 /****************************************************************
10405  _spoolss_ReplyOpenPrinter
10406 ****************************************************************/
10407
10408 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10409                                  struct spoolss_ReplyOpenPrinter *r)
10410 {
10411         p->rng_fault_state = true;
10412         return WERR_NOT_SUPPORTED;
10413 }
10414
10415 /****************************************************************
10416  _spoolss_RouterReplyPrinter
10417 ****************************************************************/
10418
10419 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10420                                    struct spoolss_RouterReplyPrinter *r)
10421 {
10422         p->rng_fault_state = true;
10423         return WERR_NOT_SUPPORTED;
10424 }
10425
10426 /****************************************************************
10427  _spoolss_ReplyClosePrinter
10428 ****************************************************************/
10429
10430 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10431                                   struct spoolss_ReplyClosePrinter *r)
10432 {
10433         p->rng_fault_state = true;
10434         return WERR_NOT_SUPPORTED;
10435 }
10436
10437 /****************************************************************
10438  _spoolss_AddPortEx
10439 ****************************************************************/
10440
10441 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10442                           struct spoolss_AddPortEx *r)
10443 {
10444         p->rng_fault_state = true;
10445         return WERR_NOT_SUPPORTED;
10446 }
10447
10448 /****************************************************************
10449  _spoolss_RouterFindFirstPrinterChangeNotification
10450 ****************************************************************/
10451
10452 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10453                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10454 {
10455         p->rng_fault_state = true;
10456         return WERR_NOT_SUPPORTED;
10457 }
10458
10459 /****************************************************************
10460  _spoolss_SpoolerInit
10461 ****************************************************************/
10462
10463 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10464                             struct spoolss_SpoolerInit *r)
10465 {
10466         p->rng_fault_state = true;
10467         return WERR_NOT_SUPPORTED;
10468 }
10469
10470 /****************************************************************
10471  _spoolss_ResetPrinterEx
10472 ****************************************************************/
10473
10474 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10475                                struct spoolss_ResetPrinterEx *r)
10476 {
10477         p->rng_fault_state = true;
10478         return WERR_NOT_SUPPORTED;
10479 }
10480
10481 /****************************************************************
10482  _spoolss_RouterReplyPrinterEx
10483 ****************************************************************/
10484
10485 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10486                                      struct spoolss_RouterReplyPrinterEx *r)
10487 {
10488         p->rng_fault_state = true;
10489         return WERR_NOT_SUPPORTED;
10490 }
10491
10492 /****************************************************************
10493  _spoolss_44
10494 ****************************************************************/
10495
10496 WERROR _spoolss_44(struct pipes_struct *p,
10497                    struct spoolss_44 *r)
10498 {
10499         p->rng_fault_state = true;
10500         return WERR_NOT_SUPPORTED;
10501 }
10502
10503 /****************************************************************
10504  _spoolss_SetPort
10505 ****************************************************************/
10506
10507 WERROR _spoolss_SetPort(struct pipes_struct *p,
10508                         struct spoolss_SetPort *r)
10509 {
10510         p->rng_fault_state = true;
10511         return WERR_NOT_SUPPORTED;
10512 }
10513
10514 /****************************************************************
10515  _spoolss_4a
10516 ****************************************************************/
10517
10518 WERROR _spoolss_4a(struct pipes_struct *p,
10519                    struct spoolss_4a *r)
10520 {
10521         p->rng_fault_state = true;
10522         return WERR_NOT_SUPPORTED;
10523 }
10524
10525 /****************************************************************
10526  _spoolss_4b
10527 ****************************************************************/
10528
10529 WERROR _spoolss_4b(struct pipes_struct *p,
10530                    struct spoolss_4b *r)
10531 {
10532         p->rng_fault_state = true;
10533         return WERR_NOT_SUPPORTED;
10534 }
10535
10536 /****************************************************************
10537  _spoolss_4c
10538 ****************************************************************/
10539
10540 WERROR _spoolss_4c(struct pipes_struct *p,
10541                    struct spoolss_4c *r)
10542 {
10543         p->rng_fault_state = true;
10544         return WERR_NOT_SUPPORTED;
10545 }
10546
10547 /****************************************************************
10548  _spoolss_53
10549 ****************************************************************/
10550
10551 WERROR _spoolss_53(struct pipes_struct *p,
10552                    struct spoolss_53 *r)
10553 {
10554         p->rng_fault_state = true;
10555         return WERR_NOT_SUPPORTED;
10556 }
10557
10558 /****************************************************************
10559  _spoolss_AddPerMachineConnection
10560 ****************************************************************/
10561
10562 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
10563                                         struct spoolss_AddPerMachineConnection *r)
10564 {
10565         p->rng_fault_state = true;
10566         return WERR_NOT_SUPPORTED;
10567 }
10568
10569 /****************************************************************
10570  _spoolss_DeletePerMachineConnection
10571 ****************************************************************/
10572
10573 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
10574                                            struct spoolss_DeletePerMachineConnection *r)
10575 {
10576         p->rng_fault_state = true;
10577         return WERR_NOT_SUPPORTED;
10578 }
10579
10580 /****************************************************************
10581  _spoolss_EnumPerMachineConnections
10582 ****************************************************************/
10583
10584 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
10585                                           struct spoolss_EnumPerMachineConnections *r)
10586 {
10587         p->rng_fault_state = true;
10588         return WERR_NOT_SUPPORTED;
10589 }
10590
10591 /****************************************************************
10592  _spoolss_5a
10593 ****************************************************************/
10594
10595 WERROR _spoolss_5a(struct pipes_struct *p,
10596                    struct spoolss_5a *r)
10597 {
10598         p->rng_fault_state = true;
10599         return WERR_NOT_SUPPORTED;
10600 }
10601
10602 /****************************************************************
10603  _spoolss_5b
10604 ****************************************************************/
10605
10606 WERROR _spoolss_5b(struct pipes_struct *p,
10607                    struct spoolss_5b *r)
10608 {
10609         p->rng_fault_state = true;
10610         return WERR_NOT_SUPPORTED;
10611 }
10612
10613 /****************************************************************
10614  _spoolss_5c
10615 ****************************************************************/
10616
10617 WERROR _spoolss_5c(struct pipes_struct *p,
10618                    struct spoolss_5c *r)
10619 {
10620         p->rng_fault_state = true;
10621         return WERR_NOT_SUPPORTED;
10622 }
10623
10624 /****************************************************************
10625  _spoolss_5d
10626 ****************************************************************/
10627
10628 WERROR _spoolss_5d(struct pipes_struct *p,
10629                    struct spoolss_5d *r)
10630 {
10631         p->rng_fault_state = true;
10632         return WERR_NOT_SUPPORTED;
10633 }
10634
10635 /****************************************************************
10636  _spoolss_5e
10637 ****************************************************************/
10638
10639 WERROR _spoolss_5e(struct pipes_struct *p,
10640                    struct spoolss_5e *r)
10641 {
10642         p->rng_fault_state = true;
10643         return WERR_NOT_SUPPORTED;
10644 }
10645
10646 /****************************************************************
10647  _spoolss_5f
10648 ****************************************************************/
10649
10650 WERROR _spoolss_5f(struct pipes_struct *p,
10651                    struct spoolss_5f *r)
10652 {
10653         p->rng_fault_state = true;
10654         return WERR_NOT_SUPPORTED;
10655 }
10656
10657 /****************************************************************
10658  _spoolss_60
10659 ****************************************************************/
10660
10661 WERROR _spoolss_60(struct pipes_struct *p,
10662                    struct spoolss_60 *r)
10663 {
10664         p->rng_fault_state = true;
10665         return WERR_NOT_SUPPORTED;
10666 }
10667
10668 /****************************************************************
10669  _spoolss_61
10670 ****************************************************************/
10671
10672 WERROR _spoolss_61(struct pipes_struct *p,
10673                    struct spoolss_61 *r)
10674 {
10675         p->rng_fault_state = true;
10676         return WERR_NOT_SUPPORTED;
10677 }
10678
10679 /****************************************************************
10680  _spoolss_62
10681 ****************************************************************/
10682
10683 WERROR _spoolss_62(struct pipes_struct *p,
10684                    struct spoolss_62 *r)
10685 {
10686         p->rng_fault_state = true;
10687         return WERR_NOT_SUPPORTED;
10688 }
10689
10690 /****************************************************************
10691  _spoolss_63
10692 ****************************************************************/
10693
10694 WERROR _spoolss_63(struct pipes_struct *p,
10695                    struct spoolss_63 *r)
10696 {
10697         p->rng_fault_state = true;
10698         return WERR_NOT_SUPPORTED;
10699 }
10700
10701 /****************************************************************
10702  _spoolss_64
10703 ****************************************************************/
10704
10705 WERROR _spoolss_64(struct pipes_struct *p,
10706                    struct spoolss_64 *r)
10707 {
10708         p->rng_fault_state = true;
10709         return WERR_NOT_SUPPORTED;
10710 }
10711
10712 /****************************************************************
10713  _spoolss_65
10714 ****************************************************************/
10715
10716 WERROR _spoolss_65(struct pipes_struct *p,
10717                    struct spoolss_65 *r)
10718 {
10719         p->rng_fault_state = true;
10720         return WERR_NOT_SUPPORTED;
10721 }
10722
10723 /****************************************************************
10724  _spoolss_GetCorePrinterDrivers
10725 ****************************************************************/
10726
10727 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
10728                                       struct spoolss_GetCorePrinterDrivers *r)
10729 {
10730         p->rng_fault_state = true;
10731         return WERR_NOT_SUPPORTED;
10732 }
10733
10734 /****************************************************************
10735  _spoolss_67
10736 ****************************************************************/
10737
10738 WERROR _spoolss_67(struct pipes_struct *p,
10739                    struct spoolss_67 *r)
10740 {
10741         p->rng_fault_state = true;
10742         return WERR_NOT_SUPPORTED;
10743 }
10744
10745 /****************************************************************
10746  _spoolss_GetPrinterDriverPackagePath
10747 ****************************************************************/
10748
10749 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
10750                                             struct spoolss_GetPrinterDriverPackagePath *r)
10751 {
10752         p->rng_fault_state = true;
10753         return WERR_NOT_SUPPORTED;
10754 }
10755
10756 /****************************************************************
10757  _spoolss_69
10758 ****************************************************************/
10759
10760 WERROR _spoolss_69(struct pipes_struct *p,
10761                    struct spoolss_69 *r)
10762 {
10763         p->rng_fault_state = true;
10764         return WERR_NOT_SUPPORTED;
10765 }
10766
10767 /****************************************************************
10768  _spoolss_6a
10769 ****************************************************************/
10770
10771 WERROR _spoolss_6a(struct pipes_struct *p,
10772                    struct spoolss_6a *r)
10773 {
10774         p->rng_fault_state = true;
10775         return WERR_NOT_SUPPORTED;
10776 }
10777
10778 /****************************************************************
10779  _spoolss_6b
10780 ****************************************************************/
10781
10782 WERROR _spoolss_6b(struct pipes_struct *p,
10783                    struct spoolss_6b *r)
10784 {
10785         p->rng_fault_state = true;
10786         return WERR_NOT_SUPPORTED;
10787 }
10788
10789 /****************************************************************
10790  _spoolss_6c
10791 ****************************************************************/
10792
10793 WERROR _spoolss_6c(struct pipes_struct *p,
10794                    struct spoolss_6c *r)
10795 {
10796         p->rng_fault_state = true;
10797         return WERR_NOT_SUPPORTED;
10798 }
10799
10800 /****************************************************************
10801  _spoolss_6d
10802 ****************************************************************/
10803
10804 WERROR _spoolss_6d(struct pipes_struct *p,
10805                    struct spoolss_6d *r)
10806 {
10807         p->rng_fault_state = true;
10808         return WERR_NOT_SUPPORTED;
10809 }