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