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