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